所以我认为负数,当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
为什么会这样,是否有解决方法?
所以我认为负数,当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;
不要按照其他答案中的建议执行额外的 mod 操作。它们非常昂贵且不必要。
在 C 和 Objective-C 中,除法和取模运算符执行向零截断。 a / b
是floor(a / b)
if a / b > 0
,否则是ceiling(a / b)
if a / b < 0
。总是这样a == (a / b) * b + (a % b)
,除非当然b
是 0。因此,positive % positive == positive
, positive % negative == positive
, negative % positive == negative
, 和negative % negative == negative
(您可以计算出所有 4 种情况的逻辑,尽管这有点棘手)。
如果 n 的范围有限,那么您只需添加一个大于最小值绝对值的已知常数倍数 3 即可获得所需的结果。
例如,如果 n 限制为 -1000..2000,那么您可以使用以下表达式:
result = (n+1002) % 3;
确保最大值加上你的常数在求和时不会溢出。
我们有一个语言问题:
math-er-says: 我把这个数字加上那个数字 mod other-number code-er-hears:我将两个数字相加,然后将结果除以 other-number code-er-says:负数呢? 数学家说:什么?字段 mod other-number 没有负数的概念? code-er-says:字段是什么?...
在这种情况下,您需要数学家的 mod 运算符并使用余数函数。您可以将余数运算符转换为数学家的 mod 运算符,方法是检查每次减法时是否跌落底部。
我也期望一个正数,但我从 ISO/IEC 14882:2003 中找到了这个:编程语言——C++,5.6.4(在关于模运算的维基百科文章中找到):
二元 % 运算符产生第一个表达式除以第二个表达式的余数。.... 如果两个操作数都是非负数,则余数是非负数;如果不是,则余数的符号是实现定义的
如果这将是行为,并且您知道它会是,那么 for m % n = r
,只需使用r = n + r
. 如果您不确定这里会发生什么,请使用 then r = r % n
。
编辑:总而言之,使用r = ( n + ( m % n ) ) % n
JavaScript 也这样做。我已经被它抓住了几次。将其视为围绕零的反映,而不是延续。
为什么:因为这是 C 标准中指定 mod 运算符的方式(请记住,Objective-C 是 C 的扩展)。它让我认识的大多数人(比如我)感到困惑,因为它令人惊讶,你必须记住它。
至于解决方法:我会使用 uncleo 的。
UncleO 的答案可能更可靠,但如果你想在一行上做,并且你确定负值不会比 mod 的单次迭代更负(例如,如果你只减去大多数mod值在任何时候)你可以将它简化为一个表达式:
int result = (n + 3) % 3;
由于无论如何您都在进行 mod,因此将 3 添加到初始值没有任何效果,除非n 为负数(但不小于 -3),在这种情况下,它会导致结果为预期的正模数。
其余的有两种选择,符号取决于语言。ANSI C 选择被除数的符号。我怀疑这就是你看到 Objective-C 也这样做的原因。 另请参阅 wikipedia 条目。
不仅是java脚本,几乎所有语言都显示错误答案'coneybeare所说的是正确的,当我们有模式时,我们必须得到余数余数只是除法后剩下的,它应该是一个正整数......
如果您检查数字行,您可以理解
我在 VB 中也面临同样的问题,这让我不得不强制添加额外的检查,比如如果结果是否定的,我们必须将除数添加到结果中
代替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)
在你的代码中使用它应该可以正常工作。