23

Perl

print 2 % -18;

-->

-16

Tcl

puts [expr {2 % -18}]

-->

-16

但是 VBScript

wscript.echo 2 mod -18

-->

2

为什么有区别?

4

4 回答 4

31

维基百科的答案在这里很有帮助。

一个简短的总结是任何整数都可以定义为

a = qn + r

其中所有这些字母都是整数,并且

0 <= |r| < |n|。

几乎每种编程语言都要求 (a/n) * n + (a%n) = a。所以模数的定义几乎总是取决于整数除法的定义。整数除以负数有两种选择:2/-18 = 0 或 2/-18 = -1。根据您的语言的正确性,通常会更改 % 运算符。

这是因为 2 = (-1) * -18 + (-16) 和 2 = 0 * -18 + 2。

对于 Perl,情况很复杂。手册页说:“请注意,当使用整数在范围内时,“%”使您可以直接访问由 C 编译器实现的模运算符。该运算符对于负操作数的定义不是很好,但它会执行得更快。 " 因此,如果使用整数在范围内,它可以为 Perl(如 C)选择任一选项。如果使用整数不在范围内,则手册说“如果 $b 为负数,则 $a % $b 是 $a 减去不小于 $a 的 $b 的最小倍数(即结果将小于或等于零)。”

于 2009-01-16T13:50:15.083 回答
9

维基百科的“模运算”页面很好地解释了这一点。我不会尝试在这里做得更好,因为我可能会犯一个微妙但重要的错误。

它的问题在于您可以以不同的方式定义“余数”或“模数”,并且不同的语言选择了不同的选项来实现。

于 2009-01-16T13:39:03.950 回答
4

在除以一个数和一个除数(其中一个是负数)之后,您至少有两种方法可以将它们分成商和余数,例如商 * 除数 + 余数 = 数:您可以将商四舍五入到负无穷大,或趋向于零。

许多语言只选择一种。

我忍不住要指出Common Lisp两者都提供。

于 2009-01-16T15:46:14.817 回答
3

python,当然,明确地通知你

>>> divmod(2,-18)
(-1, -16)
于 2009-03-13T03:55:16.763 回答