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

  • 本文关键字:运算 例如 -10%3 Perl perl
  • 更新时间 :
  • 英文 :


我正在学习Perl(5.14),我有点拘泥于负数的模运算。作为一个例子,让我们来看看10%3的变化。

首先,

perl -le 'print -10%-3'

如预期的那样产生-1

但是,

perl -le 'print -10%3'

得到CCD_ 2。

而且,

perl -le 'print 10%-3'

得到CCD_ 3。

我不理解最后两个结果。对于10%3的任何变化,我预计结果只有1或-1。为什么结果应该返回2,无论是正的还是负的?

您发现了一个perl5规范错误/功能,很可能永远无法修复。这个modulo vs i_modulo的错误甚至被记录为这样,对modulo有一个奇怪的定义,它偏离了数学定义和标准C库libc中的实现。

中的文档http://perldoc.perl.org/perlop.html#Multiplicative-运算符只描述一种情况,而不是第二种情况。忘了讲述整个故事。

"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)
}

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

这个bug甚至被提升到了第16个版本,在第15个版本中被定义为鹦鹉和魔。我不确定jvm后端是否也使用了破解来使用奇怪的perl5定义。

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

这摘自Perl文档:乘法运算符

二进制%是模运算符,它计算第一个自变量相对于第二个自变量的除法余数。

给定整数操作数$a$b:

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

请注意,当use integer在作用域中时,%允许您直接访问由C编译器实现的模运算符。这个运算符并没有很好地定义为负操作数,但它会执行得更快。

相关内容

最新更新