[英]Why is the behavior of the modulo operator (%) different between C and Ruby for negative integers?
我在这里运行了一些代码。 我试过-40 % 3
。 它给了我输出2
。 当我在 C 中执行相同的操作时,我得到:
int i = (-40) % 3
printf("%d", i);
输出是
-1
两种语言如何在内部执行模运算?
维基说:
给定两个正数
a
(被除数)和n
(除数),模 n (缩写为 mod n)是a by n
的余数。
....当a
或n
为负数时,幼稚的定义就会失效,并且编程语言在定义这些值的方式上有所不同。
现在的问题是为什么-40 % 3
在 Ruby 中是2
或者换句话说,它背后的数学是什么?
让我们从欧几里得除法开始,它指出:
给定两个整数
a
和n
,其中n ≠ 0
,存在唯一整数q
和r
使得a = n*q + r
且0 ≤ r < |n|
, 其中|n|
表示n
的绝对值。
现在注意商的两个定义:
q=floor(a/n)
,余数r
是: 这里商 ( q
) 总是向下舍入(即使它已经是负数),余数 ( r
) 与除数具有相同的符号。
q = sgn(a)floor(|a| / n)
sgn
是符号函数。
余数 ( r
) 与被除数 ( a
) 的符号相同。
现在一切都取决于q
:
- 如果实现符合定义
1
并将q
定义为floor(a/n)
则40 % 3
值为1
,-40 % 3
值为2
。 这似乎是 Ruby 的情况。- 如果实现符合定义
2
并将q
定义为sgn(a)floor(|a| / n)
,则40 % 3
值为1
,-40 % 3
值为-1
。 这似乎是 C 和 Java 的情况。
在 Java 和 C 中,模运算的结果与被除数具有相同的符号,因此 -1 是您示例中的结果。
在 Ruby 中,它与除数具有相同的符号,因此根据您的示例,结果为 +2。
在 ruby 实现中,当分子为负而分母为正时,取模运算符回答的问题是,“从分子中减去时,允许分母整除的最小正数是多少?”
在所有实现中,当分子和分母都是正数时,要回答的问题是:“当从分子中减去时,允许分母平均除以结果的最小正数是多少?”
因此,您可以看到 ruby 实现始终在回答相同的问题,即使结果起初并不直观。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.