Perl:理解负数的模运算(例如-10%3)

时间:2013-12-19 21:17:13

标签: perl

我正在学习Perl(5.14)并且我有点卡在模数上,带有负数。举个例子,让我们来看看10%3的变化。

首先,

perl -le 'print -10%-3'

按预期收取-1

但是,

perl -le 'print -10%3'

收益2

perl -le 'print 10%-3'

收益-2

我不明白最后两个结果。我认为10%3的任何变化都只有1或-1。结果为什么要返回2,无论是正面还是负面?

2 个答案:

答案 0 :(得分:3)

Perl通常使用与机器无关的算术模运算符。

这取自Perl Documentation: Multiplicative Operators

二进制%是模运算符,它根据第二个参数计算第一个参数的除法余数。

给定整数操作数$a$b

  • 如果$b为正数,则$a % $b$a减去$b的最大倍数小于或等于$a
  • 如果$b为否定,则$a % $b$a减去不小于$b的{​​{1}}的最小倍数(即结果将小于或等于零)。
  • 如果操作数$a$a是浮点值且$b(即$b)的绝对值小于abs($b),则仅(UV_MAX + 1)$a的整数部分将在操作中使用(注意:此处$b表示无符号整数类型的最大值)。
  • 如果右操作数(UV_MAX)的绝对值大于或等于abs($b)(UV_MAX + 1)计算等式中的浮点余数%$r)其中$r = $a - $i*$b是某个整数,使$i具有与右操作数$r相同的符号(而不是像C函数那样的左操作数$b $a)并且绝对值小于fmod()的绝对值。

请注意,当$b在范围内时,use integer可让您直接访问由C编译器实现的模运算符。这个运算符没有为负操作数定义,但它会更快地执行。

答案 1 :(得分:1)

您发现了很可能永远不会修复的perl5规范错误/功能。 这个modulo vs i_modulo bug甚至被记录在案,其中有一个奇怪的modulo定义,它偏离了数学定义和libc(标准C库)中的实现。

http://perldoc.perl.org/perlop.html#Multiplicative-Operators中的文档仅描述了一个案例,而不是第二个案例。忘了讲述整个故事。

"If $b is negative, then $a % $b is $a minus the smallest multiple of $b
that is not less than $a (that is, the result will be less than or
equal to zero)."

因此未指定-13%4,13%-4被描述为返回-3,而不是1。 实际上-13%4返回3而不是-1。

如果没有use integer,这种perl5行为只会很奇怪。 使用use integer,您可以获得正确且快速的libc行为。

   use integer;
   print -13 % 4;  # => -1
   print  13 % -4; # => 1
   print -13 % -4; # => -1 (same with or without use integer)
   print  13 % 4;  # => 1 (same with or without use integer)

   { 
     no integer;
     print -13 % 4;  # => 3 (different to libc)
     print  13 % -4; # => -3 (different to libc)
     print -13 % -4; # => -1 (same with or without use integer)
     print  13 % 4;  # => 1 (same with or without use integer)
   }

请注意,两个参数都是文字整数常量,结果在编译时是常量折叠。但即使两个参数显然都是整数类型,常量文件夹也使用通用模运算符,而不是使用整数下使用的特定i_modulo运算符。或者使用类型化的perl扩展,在编译时两个args都是整数。

这个bug甚至被提升为perl6,在perl5中以parrot和moar定义。我不确定jvm后端是否也使用hack来使用奇怪的perl5定义。