I'm looking for a simple explanation for how Ruby's modulo operand works and why, in Ruby
puts 4 % 3 # 1
puts -4 % 3 # 2 <--why?
puts -4 % -3 # -1
but in PHP:
<?php
echo 4 % 3; # 1
echo -4 % 3; # -1
echo -4 % -3; # -1
Looks to me like -4 % 3 is actally 8 % 3 (8 being the difference between 4 and -4).
They can both be considered correct, depending on your definition. If a % n == r
, then it should hold that:
a == q*n + r
where q == a / n
.
Whether r
is positive or negative is determined by the value of q
. So in your example, either of:
-4 == -1*3 + (-1) // PHP
-4 == -2*3 + 2 // Ruby
To put it another way, the definition of %
depends on the definition of /
.
See also the table here: http://en.wikipedia.org/wiki/Modulus_operator#Remainder_calculation_for_the_modulo_operation. You'll see that this varies substantially between various programming languages.
Here's a snippet on the topic from The Ruby Programming Language, by Matz and David Flanagan.
When one (but not both) of the operands is negative, Ruby performs the integer division and modulo operations differently than languages like C, C++, and Java do (but the same as the languages Python and Tcl). Consider the quotient -7/3. Ruby rounds toward negative infinity and returns -3. C and related languages round toward zero instead and return -2. In Ruby, -a/b equals a/-b but my not equal -(a/b).
Ruby's definition of the module operation also differs from that of C and Java. In Ruby, -7%3 is 2. In C and Java, the result is -1 instead. The magnitude of the result differs, because the quotient differed. But the sign of the result differs, too. In Ruby, the sign of the result is always the sign of the second operand. In C and Java, the sign of the result is always the sign of the first operand. (Ruby's remainder method behaves like the C modulo operator.)
It actually boils down to the implementation of the language's integer casting/rounding. Since the actual equation is:
a - (n * int(a/n))
It is the int(a/n)
portion of the equation that differs. If a == -4
and n == 3
, PHP will return -1, while Ruby will produce -2. Now the equation looks like this in Ruby:
-4 - (3 * -2)
and this in PHP
-4 - (3 * -1)
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