43

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

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

4

12 回答 12

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

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

于 2009-06-13T04:58:32.880 回答
14

在 C 和 Objective-C 中,除法和取模运算符执行向零截断。 a / bfloor(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 种情况的逻辑,尽管这有点棘手)。

于 2009-06-13T04:16:15.273 回答
9

如果 n 的范围有限,那么您只需添加一个大于最小值绝对值的已知常数倍数 3 即可获得所需的结果。

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

result = (n+1002) % 3;

确保最大值加上你的常数在求和时不会溢出。

于 2009-06-13T09:01:08.430 回答
7

我们有一个语言问题:

math-er-says: 我把这个数字加上那个数字 mod other-number
code-er-hears:我将两个数字相加,然后将结果除以 other-number
code-er-says:负数呢?
数学家说:什么?字段 mod other-number 没有负数的概念?
code-er-says:字段是什么?...
  • 这个对话中的数学人正在谈论在循环数轴上做数学。如果你减去底部,你会环绕到顶部。
  • 代码人员正在谈论计算余数的运算符。

在这种情况下,您需要数学家的 mod 运算符并使用余数函数。您可以将余数运算符转换为数学家的 mod 运算符,方法是检查每次减法时是否跌落底部。

于 2009-07-17T23:23:55.710 回答
4

我也期望一个正数,但我从 ISO/IEC 14882:2003 中找到了这个:编程语言——C++,5.6.4(在关于模运算的维基百科文章中找到):

二元 % 运算符产生第一个表达式除以第二个表达式的余数。.... 如果两个操作数都是非负数,则余数是非负数;如果不是,则余数的符号是​​实现定义的

于 2009-06-13T04:15:37.927 回答
4

如果这将是行为,并且您知道它会是,那么 for m % n = r,只需使用r = n + r. 如果您不确定这里会发生什么,请使用 then r = r % n

编辑:总而言之,使用r = ( n + ( m % n ) ) % n

于 2009-06-13T04:19:59.853 回答
1

JavaScript 也这样做。我已经被它抓住了几次。将其视为围绕零的反映,而不是延续。

于 2009-06-13T04:22:05.947 回答
1

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

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

于 2009-06-13T09:50:41.367 回答
1

UncleO 的答案可能更可靠,但如果你想在一行上做,并且你确定负值不会比 mod 的单次迭代更负(例如,如果你只减去大多数mod值在任何时候)你可以将它简化为一个表达式:

int result = (n + 3) % 3;

由于无论如何您都在进行 mod,因此将 3 添加到初始值没有任何效果,除非n 为负数(但不小于 -3),在这种情况下,它会导致结果为预期的正模数。

于 2014-11-06T19:41:17.310 回答
0

其余的有两种选择,符号取决于语言。ANSI C 选择被除数的符号。我怀疑这就是你看到 Objective-C 也这样做的原因。 另请参阅 wikipedia 条目

于 2009-06-13T04:19:20.307 回答
0

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

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

我在 VB 中也面临同样的问题,这让我不得不强制添加额外的检查,比如如果结果是否定的,我们必须将除数添加到结果中

于 2011-02-07T07:50:27.910 回答
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)在你的代码中使用它应该可以正常工作。

于 2016-07-07T07:46:04.313 回答