负数的奇怪的 Objective-C Mod 行为
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/989943/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Weird Objective-C Mod Behavior for Negative Numbers
提问by coneybeare
So I thought that negative numbers, when mod'ed should be put into positive space... I cant get this to happen in objective-c
所以我认为负数,当 mod'ed 应该放入正空间......我不能在objective-c中发生这种情况
I expect this:
我期待这个:
-1 % 3 = 2
0 % 3 = 0
1 % 3 = 1
2 % 3 = 2
But get this
但是得到这个
-1 % 3 = -1
0 % 3 = 0
1 % 3 = 1
2 % 3 = 2
Why is this and is there a workaround?
为什么会这样,是否有解决方法?
回答by UncleO
result = n % 3;
if( result < 0 ) result += 3;
Don't perform extra mod operations as suggested in the other answers. They are very expensive and unnecessary.
不要按照其他答案中的建议执行额外的 mod 操作。它们非常昂贵且不必要。
回答by Adam Rosenfield
In C and Objective-C, the division and modulus operators perform truncation towards zero. a / bis floor(a / b)if a / b > 0, otherwise it is ceiling(a / b)if a / b < 0. It is always the case that a == (a / b) * b + (a % b), unless of course bis 0. As a consequence, positive % positive == positive, positive % negative == positive, negative % positive == negative, and negative % negative == negative(you can work out the logic for all 4 cases, although it's a little tricky).
在 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 种情况的逻辑,尽管这有点棘手)。
回答by Peter N Lewis
If n has a limited range, then you can get the result you want simply by adding a known constant multiple of 3 that is greater that the absolute value of the minimum.
如果 n 的范围有限,那么您只需添加一个大于最小值的绝对值的已知常数倍数 3,即可得到您想要的结果。
For example, if n is limited to -1000..2000, then you can use the expression:
例如,如果 n 限制为 -1000..2000,则可以使用以下表达式:
result = (n+1002) % 3;
Make sure the maximum plus your constant will not overflow when summed.
确保最大值加上您的常数在求和时不会溢出。
回答by Arthur Ulfeldt
We have a problem of language:
我们有语言问题:
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? ...
- the math person in this conversations is talking about doing math in a circular number line. If you subtract off the bottom you wrap around to the top.
- the code person is talking about an operator that calculates remainder.
- 本次对话中的数学人员正在谈论在圆形数轴上进行数学运算。如果从底部减去,则环绕到顶部。
- 代码人员正在谈论计算余数的运算符。
In this case you want the mathematician's mod operator and have the remainder function at your disposal. you can convert the remainder operator into the mathematician's mod operator by checking to see if you fell of the bottom each time you do subtraction.
在这种情况下,您需要数学家的 mod 运算符,并且您可以使用余数函数。您可以通过检查每次做减法时是否跌倒底部,将余数运算符转换为数学家的 mod 运算符。
回答by maxwellb
If this will be the behavior, and you know that it will be, then for m % n = r, just use r = n + r. If you're unsure of what will happen here, use then r = r % n.
如果这将是行为,并且您知道它将是,那么 for m % n = r,只需使用r = n + r. 如果您不确定这里会发生什么,请使用 then r = r % n。
Edit: To sum up, use r = ( n + ( m % n ) ) % n
编辑:总而言之,使用 r = ( n + ( m % n ) ) % n
回答by e.James
I would have expected a positive number, as well, but I found this, from ISO/IEC 14882:2003 : Programming languages -- C++, 5.6.4 (found in the Wikipedia article on the modulus operation):
我也期望一个正数,但我从 ISO/IEC 14882:2003 中找到了这个:编程语言——C++,5.6.4(在关于模数运算的维基百科文章中找到):
The binary % operator yields the remainder from the division of the first expression by the second. .... If both operands are nonnegative then the remainder is nonnegative; if not, the sign of the remainder is implementation-defined
二元 % 运算符产生第一个表达式除以第二个表达式的余数。.... 如果两个操作数都为非负,则余数为非负;如果不是,余数的符号是实现定义的
回答by Nosredna
JavaScript does this, too. I've been caught by it a couple times. Think of it as a reflection around zero rather than a continuation.
JavaScript 也这样做。我已经被它抓住了几次。将其视为围绕零的反映而不是延续。
回答by Tobias
Why: because that is the way the mod operator is specified in the C-standard (Remember that Objective-C is an extension of C). It confuses most people I know (like me) because it is surprising and you have to remember it.
为什么:因为这是 C 标准中指定 mod 运算符的方式(请记住,Objective-C 是 C 的扩展)。它让我认识的大多数人(如我)感到困惑,因为它令人惊讶,您必须记住它。
As to a workaround: I would use uncleo's.
至于解决方法:我会使用uncleo的。
回答by devios1
UncleO's answer is probably more robust, but if you want to do it on a single line, and you're certain the negative value will not be more negativethan a single iteration of the mod (for example if you're only ever subtracting at most the mod value at any time) you can simplify it to a single expression:
UncleO 的答案可能更可靠,但如果你想在一行上做,并且你确定负值不会比 mod 的单次迭代更负(例如,如果你只减去大多数时候的 mod 值)您可以将其简化为单个表达式:
int result = (n + 3) % 3;
Since you're doing the mod anyway, adding 3 to the initial value has no effect unlessn is negative (but not less than -3) in which case it causes result to be the expected positive modulus.
由于您无论如何都在进行 mod,因此将 3 添加到初始值没有任何影响,除非n 为负(但不小于 -3),在这种情况下,它会导致结果为预期的正模数。
回答by Albert Renshaw
Instead of a%b
代替 a%b
Use: a-b*floor((float)a/(float)b)
用: a-b*floor((float)a/(float)b)
You're expecting remainderand are using modulo. In math they are the same thing, in C they are different. GNU-C has Rem() and Mod(), objective-c only has mod() so you will have to use the code above to simulate rem function (which is the same as mod in the math world, but not in the programming world [for most languages at least])
您期待余数并使用modulo。在数学中它们是相同的东西,在 C 中它们是不同的。GNU-C 有 Rem() 和 Mod(),objective-c 只有 mod() 所以你必须使用上面的代码来模拟 rem 函数(这与数学世界中的 mod 相同,但在编程中不同世界 [至少对于大多数语言而言])
Also note you could define an easy to use macro for this.
另请注意,您可以为此定义一个易于使用的宏。
#define rem(a,b) ((int)(a-b*floor((float)a/(float)b)))
#define rem(a,b) ((int)(a-b*floor((float)a/(float)b)))
Then you could just use rem(-1,3)in your code and it should work fine.
然后你可以rem(-1,3)在你的代码中使用它,它应该可以正常工作。

