Perl
print 2 % -18;
-16
Tcl
puts [expr {2 % -18}]
-16
但VBScript
wscript.echo 2 mod -18
2
为什么会有这样的差别?
维基百科答案对此相当有帮助。
简短地说,任何整数都可以定义为
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 来说,情况很复杂。 手册页面上写道:"请注意,当 use integer 处于作用域中时,“%”将直接访问由您的 C 编译器实现的模数运算符。该运算符对于负操作数并没有那么好的定义,但它将执行更快。" 因此,如果 use integer 处于作用域内,Perl(如 C)可以选择其中任一选项。 如果 use integer 不在作用域内,则手册上写道:"如果 $b 为负,则 $a % $b 是 $a 减去不小于 $a 的最小倍数的 $b(即结果将小于或等于零)。
维基百科的“模运算”页面已经很好地解释了它。我不会试图在这里做得更好,因为我可能会犯一个微妙但重要的错误。
关键是您可以以不同的方式定义“余数”或“模数”,不同的编程语言选择不同的选项来实现。
在一个数和一个除数中,如果有一个是负数,那么可以有至少两种方式将它们分开成商和余数,使得商*除数+余数=数:你可以将商向负无穷舍入,也可以向零舍入。
许多编程语言只选择其中一种。
我不禁要指出Common Lisp提供了这两种方式。
当然,Python会明确地告诉你
>>> divmod(2,-18)
(-1, -16)