Why are negative numbers rounded down after division in Ruby?

1.4k views Asked by At

I am looking through a documentation on divmod. Part of a table showing the difference between methods div, divmod, modulo, and remainder is displayed below:

enter image description here

Why is 13.div(-4) rounded to -4 and not to -3? Is there any rule or convention in Ruby to round down negative numbers? If so, why is the following code not rounding down?

-3.25.round()  #3
1

There are 1 answers

4
Neil Slater On BEST ANSWER

13.div(-4) == -4 and 13.modulo(-4) == -3 so that

(-4 * -4) + -3 == 13

and you get the consistent relationship

(b * (a/b)) + a.modulo(b) == a

Why is 13.div(-4) rounded to -4 and not to -3?

This is a misconception. 13.div(-4) is not really rounded at all. It is integer division, and follows self-consistent rules for working with integers and modular arithmetic. The rounding logic described in your link fits with it, and is then applied consistently when dealing with the same divmod operation when one or both the parameters are Floats. Mathematical operations on negative or fractional numbers are often extended from simpler, more intuitive results on positive integers in this kind of way. E.g. this follows similar logic to how fractional and negative powers, or non-integer factorials are created from their positive integer variants.

In this case, it's all about self-consistency of divmod, but not about rounding in general.

Ruby's designers had a choice to make when dealing with negative numbers, not all languages will give the same result. However, once it was decided Ruby would return sign of modulo result matching the divisor (as opposed to matching the division as a whole), that set how the rest of the numbers work.

Is there any rule or convention in Ruby to round down negative numbers?

Yes. Rounding a float number means to return the numerically closest integer. When there are two equally close integers, Ruby rounds to the integer furthest from 0. This is entirely separate design decision from how integer division and modulo arithmetic methods work.

If so, why is the following code not rounding down? -3.25.round() #3

I assume you mean the result to read -3. The round method does not "round down". It does "round closest". -3 is the closest integer to -3.25. Ruby's designers did have to make a choice though, what to do with -3.5.round() # -4. Some languages would instead return a -3 when rounding that number.