负数的奇怪Objective-C Mod行为
所以我认为,负数,当mod'ed应放入积极的空间…我不能得到这个发生在objective-c
我期待这一点:
-1 % 3 = 2 0 % 3 = 0 1 % 3 = 1 2 % 3 = 2
但是得到这个
-1 % 3 = -1 0 % 3 = 0 1 % 3 = 1 2 % 3 = 2
为什么是这样的,有没有解决方法?
result = n % 3; if( result < 0 ) result += 3;
不要按照其他答案的build议执行额外的mod操作。 他们非常昂贵和不必要的。
在C和Objective-C中,除法和模运算符向零执行截断。 如果a / b > 0
, a / b
是floor(a / b)
,否则如果a / b < 0
则a / b < 0
。 a == (a / b) * b + (a % b)
总是这样的情况,当然b
除非是0.因此, positive % positive == positive
, positive % negative == positive
, negative % positive == negative
, negative % negative == negative
(您可以计算出所有4种情况的逻辑,尽pipe这有点棘手)。
如果n有一个有限的范围,那么你可以简单地通过添加一个已知的常数倍数3来得到你想要的结果,这个倍数大于最小值的绝对值。
例如,如果n限制为-1000..2000,则可以使用以下expression式:
result = (n+1002) % 3;
确保最大加常数不会溢出时总结。
我们有一个语言问题:
math - 呃说:我把这个数字加上这个数字mod其他数字 code-er-hears:我添加两个数字,然后用其他数字来区分结果 代码 - 呃说:负数呢? math - 说:什么? 领域mod其他数字没有负数的概念? 代码呃说:领域是什么? ...
- 在这个对话中的math人士正在谈论用数字来计算math。 如果你从底部减去你绕到顶部。
- 代码人正在谈论计算余数的算子。
在这种情况下,你需要math家的mod运算符,并有余下的function在你的处置。 您可以通过检查每次减法时是否跌倒底部来将余数运算符转换为math家的mod运算符。
我也希望有一个正数,但是我从ISO / IEC 14882:2003:编程语言-C ++ 5.6.4(在维基百科关于模数运算的文章中可以find)中发现:
二进制%运算符产生第一个expression式除以第二个expression式的余数。 ….如果两个操作数都是非负的,那么余数是非负的; 如果不是,剩余的符号是实现定义的
如果这是行为,而且你知道它会是,那么对于m % n = r
,只需使用r = n + r
。 如果您不确定在这里会发生什么,请使用r = r % n
。
编辑:总结一下,使用r = ( n + ( m % n ) ) % n
JavaScript也这样做。 我已经被抓了几次了。 把它想象成一个反映在零而不是一个延续。
为什么:因为这是在C标准中指定mod运算符的方式(请记住,Objective-C是C的扩展)。 它混淆了大多数我认识的人(比如我),因为这是令人惊讶的,你必须记住它。
至于解决方法:我会使用不清楚的。
UncleO的答案可能更强大,但是如果你想在一条线上做,而且你肯定负值不会比单一的mod迭代更负面 (例如,如果你只是在减去大多数mod值都是随时可以的),你可以把它简化为一个expression式:
int result = (n + 3) % 3;
既然你正在做mod, 除了 n是负值(但不能小于-3),在初始值上加3不会产生任何影响,在这种情况下,它会导致结果是预期的正模量。
其余的有两种select,标志取决于语言。 ANSI Cselect股息的标志。 我会怀疑这就是为什么你看到Objective-C也这样做。 请参阅wikipedia条目 。
不仅是java脚本,几乎所有的语言都显示错误的答案“什么coneybeare说是正确的,当我们有模式,我们必须得到余数余数是什么,但除以后,它应该是一个正整数….
如果你检查号码行,你可以理解这一点
我也面对同样的问题在VB中,它使我强制添加额外的检查,如果结果是否定的,我们必须将除数添加到结果
而不是a%b
用途: ab*floor((float)a/(float)b)
您期待余数 ,并使用模数 。 在math上它们是一样的,在C中它们是不同的。 GNU-C有Rem()和Mod(),objective-c只有mod(),所以你必须使用上面的代码来模拟rem函数(这与mod在math世界中是一样的,但是不是在编程中世界[对于大多数语言至less])
另外请注意,您可以为此定义一个易于使用的macros。
#define rem(a,b) ((int)(ab*floor((float)a/(float)b)))
那么你可以在你的代码中使用rem(-1,3)
,它应该可以正常工作。