Interesting behaviour in Ruby’s division and modulo operators
My copy of The Ruby Programming Language has finally arrived and of course that I started reading it. One of my first findings about the language semantics has to do with mathematics, more specifically, division and modulo.
As a long time Java programmer, most of my expectations about math in programming languages come from this background, so some of the behaviors of mathematical functions in Ruby have really scared me. Let’s start with a simple example, a basic division, imagine that you have -7 and you want to divide it in 3, as we can’t divide -7 by 3 we have to reach an approximation.
During my math classes, I learned that to do this approximation I would have to use a multiplication, multiply 3 until I have a value as close as possible to -7. The closest one I can get is with -2, as -2 multiplied by 3 is -6 and I would have a remainder of -1 as -1 plus -6 is -7.
A lot of numbers, right?
Open irb on a command line and write:
-7/3
So, are you getting -2? No?
No, you are not. In Ruby, -7/3 is -3.
How the hell does this happens?
In Ruby, differently from C/C++ and Java, the result of the division between two integers where one of them is a negative number will yield a result as if it was a floating point division that rounded towards negative infinity. There is no explanation about why it is done this way (comment if you have any hints) but other languages like Python and Tcl behave in the same way.
Ideally, A divided by B with a result of C and a remainder of D is equivalent to ((C * B) + D), so this simple division would break the whole mathematical equivalence between multiplication and division, right?
Not so fast. The modulo (%) operator also behaves differently when dealing with a negative division. If you try to run (-7 % 3) you will receive 2 and ( (-3 * 3) + 2 ) is exactly -7. So, the operators keep their values equivalent, they just don’t behave the way I was expecting them to.
Another interesting thing is that if you want a modulo operator that works just like Java’s, you can call the remainder method as in:
-7.remainder(3)
This isn’t going to blow your mind or change your life forever, but it’s an interesting behavior that I didn’t have noticed yet.
PS: If you have any idea about why this happens, just drop a comment ![]()
Trackbacks
Use this link to trackback from your own site.
That’s because the division definition states that the remainder of a division should between 0 (inclusive) and |divisor| (absolute value), so, being your divisor 3, the remainder should be 0, 1, 2. So the solution of Ruby (or any other programming language with integer division) is correct.
I think you should search your math teacher and gift he/she some basic algebra books.
YoNoSoyTu is correct, integer division is not done via approximation. Consider the number 5. Integer division yields 5 = 1×3 + 2. You can see that the result is clearly 1, not 2. So you can see, that the ‘floor’ function is the appropriate way to describe what’s going on. -7/3=2.333333… and if you take it’s floor, you get -3 indeed.
Well, there doesn’t seem to be a clear truth about this, nor Java neither Ruby is wrong (and not even my math teacher
) -> http://en.wikipedia.org/wiki/Modulo_operation
Well, it seems that everyone is correct (even my good old math teacher) -> http://en.wikipedia.org/wiki/Remainder#The_inequality_satisfied_by_the_remainder