为什么C和Ruby之间的模运算符(%)的行为对于负整数是不同的?
我在这里运行一些代码。 我试过-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
的绝对值。
现在请注意商的两个定义:
1.
Donald Knuth描述了浮动除法,其中商由地板函数q=floor(a/n)
,余数r
是
商( q
)总是向下舍入(即使它已经是负数),余数( r
)与除数的符号相同 。
一些实现将商定义为
q = sgn(a)floor(|a| / n)
sgn
是signum函数。
其余( 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实现始终回答相同的问题,即使结果首先是非直观的。