I'm learning Perl (5.14) and I'm a bit stuck on modulo with negative numbers. As an example, let's take a look at variations on 10%3.
To begin,
perl -le 'print -10%-3'
yields -1, as expected.
But,
perl -le 'print -10%3'
yields 2.
And,
perl -le 'print 10%-3'
yields -2.
I do not understand the last two results. I would expect only 1 or -1 as a result for any variation on 10%3. Why should 2, either positive or negative, be returned as a result?
You found a perl5 specification bug/feature that will very likely never be fixed. This modulo vs i_modulo bug is even documented as such, with a weird definition of modulo, which deviates from the mathematical definition and the implementation in libc, the Standard C library.
The documentation in http://perldoc.perl.org/perlop.html#Multiplicative-Operators describes only one case, not the second. And forgets to tell the whole story.
"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)."
Thus -13 % 4 is unspecified, 13 % -4 is described as returning -3, not 1. In reality -13 % 4 returns 3 not -1.
This perl5 behavior is only weird without use integer.
With use integer you get proper and fast libc behavior.
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)
}
Note that with both arguments being literal integer constants, the result is constant folded at compile-time. But even with both arguments clearly being integer types, the constant folder uses the generic modulo operator, not the specific i_modulo operator, which is used under use integer. Or with a typed perl extension with both args being integers at compile-time.
This bug was even promoted to perl6, defined in parrot and moar as in perl5. I'm not sure if the jvm backend also uses a hack to use the weird perl5 definition.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With