负数的奇怪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 > 0a / bfloor(a / b) ,否则如果a / b < 0a / b < 0a == (a / b) * b + (a % b)总是这样的情况,当然b除非是0.因此, positive % positive == positivepositive % negative == positivenegative % positive == negativenegative % 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) ,它应该可以正常工作。