负数的奇怪Objective-C Mod行为

时间:2009-06-13 04:05:37

标签: objective-c modulo

所以我认为负数,当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

为什么会这样,是否有解决方法?

12 个答案:

答案 0 :(得分:53)

result = n % 3;
if( result < 0 ) result += 3;

不要按照其他答案中的建议执行额外的mod操作。它们非常昂贵且不必要。

答案 1 :(得分:14)

在C和Objective-C中,除法和模运算符执行截断为零。如果a / b,则floor(a / b)a / b > 0,否则ceiling(a / b)a / b < 0a == (a / b) * b + (a % b)总是如此,除非b当然为0.因此,positive % positive == positivepositive % negative == positivenegative % positive == negative和{{1} (你可以计算所有4个案例的逻辑,虽然这有点棘手)。

答案 2 :(得分:8)

如果n的范围有限,那么只需添加一个大于最小值绝对值的3的已知常数倍,就可以得到想要的结果。

例如,如果n限制为-1000..2000,则可以使用表达式:

result = (n+1002) % 3;

确保求和后最大加上常数不会溢出。

答案 3 :(得分:7)

我们遇到语言问题:

math-er-says: i take this number plus that number mod other-number
code-er-hears: I add two numbers and then devide the result by other-number
code-er-says: what about negative numbers?
math-er-says: WHAT? fields mod other-number don't have a concept of negative numbers?
code-er-says: field what? ...
  • 这次谈话的数学人正在谈论用循环数字线做数学。如果从底部减去,则将其环绕到顶部。
  • 代码人正在谈论计算余数的运算符。

在这种情况下,您需要数学家的mod运算符,并且可以使用余数函数。你可以将余数运算符转换为数学家的mod运算符,通过检查每次进行减法时是否掉到底部。

答案 4 :(得分:4)

我本来期望得到一个正数,但我从ISO / IEC 14882:2003:编程语言 - C ++,5.6.4(在Wikipedia article on the modulus operation中找到)中找到了这个:

  

二进制%运算符从第一个表达式除以第二个表达式得到余数。 ....如果两个操作数都是非负的,那么余数是非负的;如果没有,余数的符号是​​实现定义的

答案 5 :(得分:4)

如果这是行为,并且您知道它会是,那么对于m % n = r,只需使用r = n + r。如果您不确定此处会发生什么,请使用r = r % n

编辑:总结一下,使用r = ( n + ( m % n ) ) % n

答案 6 :(得分:1)

JavaScript也是这样做的。我被它抓了好几次。可以把它想象成零而不是延续的反映。

答案 7 :(得分:1)

为什么:因为这是在C标准中指定mod运算符的方式(请记住,Objective-C是C的扩展)。它让我认识的大多数人(比如我)感到困惑,因为它令人惊讶,你必须记住它。

至于解决方法:我会使用uncleo's。

答案 8 :(得分:1)

UncleO的答案可能更强大,但是如果你想在单行上做,并且你确定负值不会比mod的单次迭代更负面例如,如果您在任何时候只能减去mod值,那么您可以将其简化为单个表达式:

int result = (n + 3) % 3;

因为你正在做mod,所以在初始值上加3对没有影响,除非 n为负(但不小于-3),在这种情况下它会导致结果为预期正模量。

答案 9 :(得分:0)

其余部分有两种选择,符号取决于语言。 ANSI C选择被除数的符号。我怀疑这就是为什么你看到Objective-C这样做的原因。 See the wikipedia entry as well

答案 10 :(得分:0)

不仅是java脚本,几乎所有语言都显示错误答案' coneybeare说的是正确的,当我们有模式时,我们必须得到余数 剩余只不过是除法之后剩余的,它应该是一个正整数....

如果您检查数字线,则可以理解

我在VB中也面临同样的问题,它让我强行添加额外的支票 如果结果是否定的,我们必须在结果中添加除数

答案 11 :(得分:0)

而不是a%b

使用:a-b*floor((float)a/(float)b)

您期望余下并且正在使用 modulo 。在数学中它们是相同的东西,在C中它们是不同的。 GNU-C有Rem()和Mod(),objective-c只有mod()所以你必须使用上面的代码来模拟rem函数(这与数学世界中的mod相同,但不是在编程中世界[至少对大多数语言而言])

另请注意,您可以为此定义一个易于使用的宏。

#define rem(a,b) ((int)(a-b*floor((float)a/(float)b)))

然后你可以在你的代码中使用rem(-1,3),它应该可以正常工作。