负数的奇怪 Objective-C Mod 行为
所以我认为负数在修改时应该放入正空间...我无法在 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
为什么是这样并且有解决方法吗?
So I thought that negative numbers, when mod'ed should be put into positive space... I cant get this to happen in 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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(12)
不要按照其他答案中的建议执行额外的 mod 操作。 它们非常昂贵且不必要。
Don't perform extra mod operations as suggested in the other answers. They are very expensive and unnecessary.
在 C 和 Objective-C 中,除法和模运算符执行向零的截断。 如果
a / b > 则
,否则如果a / b
为floor(a / b)
0a / b
则为
ceiling(a / b)
0 。 情况始终是a == (a / b) * b + (a % b)
,除非b
为 0。因此,正 % 正 == 正
、正 % 负 == 正
、负 % 正 == 负
和负 % 负 == 负
(您可以计算出所有 4 种情况的逻辑,尽管有点棘手)。In C and Objective-C, the division and modulus operators perform truncation towards zero.
a / b
isfloor(a / b)
ifa / b > 0
, otherwise it isceiling(a / b)
ifa / b < 0
. It is always the case thata == (a / b) * b + (a % b)
, unless of courseb
is 0. As a consequence,positive % positive == positive
,positive % negative == positive
,negative % positive == negative
, andnegative % negative == negative
(you can work out the logic for all 4 cases, although it's a little tricky).如果 n 的范围有限,那么您只需添加一个大于最小值绝对值的已知常数倍 3 即可得到您想要的结果。
例如,如果 n 限制为 -1000..2000,则可以使用表达式:
确保最大值加上常量在求和时不会溢出。
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.
For example, if n is limited to -1000..2000, then you can use the expression:
Make sure the maximum plus your constant will not overflow when summed.
我们有一个语言问题:
在这种情况下,您需要数学家的 mod 运算符并拥有可供您使用的余数函数。 你可以通过检查每次做减法时是否跌入谷底,将余数运算符转换为数学家的取模运算符。
We have a problem of language:
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.
如果这将是行为,并且您知道它会是,那么对于
m % n = r
,只需使用r = n + r
。 如果您不确定这里会发生什么,请使用r = r % n
。编辑:总而言之,使用 r = ( n + ( m % n ) ) % n
If this will be the behavior, and you know that it will be, then for
m % n = r
, just user = n + r
. If you're unsure of what will happen here, use thenr = r % n
.Edit: To sum up, use
r = ( n + ( m % n ) ) % n
我本来也期望一个正数,但我从 ISO/IEC 14882:2003 中找到了这个:编程语言 -- C++,5.6.4(可在 关于模数运算的维基百科文章):
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):
JavaScript 也能做到这一点。 我已经被它抓住过几次了。 将其视为围绕零的反射而不是延续。
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.
原因:因为这是 C 标准中指定 mod 运算符的方式(请记住 Objective-C 是 C 的扩展)。 它让我认识的大多数人(比如我)感到困惑,因为它令人惊讶,而且你必须记住它。
至于解决方法:我会使用 uneo's。
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.
As to a workaround: I would use uncleo's.
UncleO 的答案可能更稳健,但如果您想在一行上执行此操作,并且您确定负值不会比 mod 的单次迭代更负(例如,如果任何时候你最多只减去 mod 值)你可以将其简化为单个表达式:
因为无论如何你都在做 mod,所以在初始值上添加 3 没有效果除非 n 为负数(但不小于 -3),在这种情况下,它会导致结果为预期的正模数。
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 negative than 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:
Since you're doing the mod anyway, adding 3 to the initial value has no effect unless n is negative (but not less than -3) in which case it causes result to be the expected positive modulus.
其余的有两种选择,符号取决于语言。 ANSI C 选择被除数的符号。 我怀疑这就是为什么你看到 Objective-C 也这样做的原因。 另请参阅维基百科条目。
There are two choices for the remainder, and the sign depends on the language. ANSI C chooses the sign of the dividend. I would suspect this is why you see Objective-C doing so also. See the wikipedia entry as well.
不仅是java脚本,几乎所有语言都显示错误答案'
coneybeare 说的是正确的,当我们有模式时,我们必须得到余数
余数只不过是除法后剩下的,它应该是一个正整数....
如果你检查数字行,你就会明白
我在 VB 中也面临着同样的问题,这让我强制添加额外的检查,例如
如果结果是负数,我们必须将除数添加到结果中
Not only java script, almost all the languages shows the wrong answer'
what coneybeare said is correct, when we have mode'd we have to get remainder
Remainder is nothing but which remains after division and it should be a positive integer....
If you check the number line you can understand that
I also face the same issue in VB and and it made me to forcefully add extra check like
if the result is a negative we have to add the divisor to the result
而不是
a%b
使用:
ab*floor((float)a/(float)b)
您期望余数并且正在使用取模。 在数学中它们是相同的,在 C 中它们是不同的。 GNU-C 有 Rem() 和 Mod(),objective-c 只有 mod(),所以你必须使用上面的代码来模拟 rem 函数(这与数学世界中的 mod 相同,但在编程中则不然) world [至少对于大多数语言])
另请注意,您可以为此定义一个易于使用的宏。
#define rem(a,b) ((int)(ab*floor((float)a/(float)b)))
然后你可以使用
rem(-1,3 )
在你的代码中,它应该可以正常工作。Instead of
a%b
Use:
a-b*floor((float)a/(float)b)
You're expecting remainder and 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])
Also note you could define an easy to use macro for this.
#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.