我认为负数在进行取模运算时应该转换成正数……但是我无法在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
为什么会这样,有没有解决方法?
我认为负数在进行取模运算时应该转换成正数……但是我无法在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;
不要像其他答案中建议的那样执行额外的模运算。它们非常昂贵且不必要。
result = (n+1002) % 3;
确保在求和时,最大值加上您的常数不会溢出。
m%n = r
,只需使用r = n + r
。如果您不确定会发生什么,请使用r = r%n
。r =(n +(m%n))%n
。UncleO的答案可能更加健壮,但是如果你想在一行代码中完成,并且你确定负值不会比模数的单次迭代更小(例如,如果你只在任何时候最多减去模数值),那么你可以简化为一个表达式:
int result = (n + 3) % 3;
既然您已经在进行修改,将初始值加3不会产生任何影响除非n为负数(但不小于-3),这种情况下会导致结果成为预期的正模数。
JavaScript也是这样做的。我被它抓住了几次。把它看作是关于零的反射,而不是延续。
不仅是 JavaScript,几乎所有的语言都会显示错误的答案。康耐比尔所说的是正确的,当我们进行模运算时,必须得到余数。余数就是除法后剩下的部分,它应该是一个正整数...
如果你查看数轴,你就能理解这一点。
我在 VB 中也遇到了同样的问题,这迫使我强制添加额外的检查,例如:如果结果为负数,我们必须将除数加到结果中。
a-b*floor((float)a/(float)b)
。 - Albert Renshaw