7

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
Yu Hao
  • 119,891
  • 44
  • 235
  • 294
gotqn
  • 42,737
  • 46
  • 157
  • 243

1 Answers1

6

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.

Neil Slater
  • 26,512
  • 6
  • 76
  • 94
  • +1. It might be worthwhile adding that in ruby the modulo operator returns the same sign as the divisor. – devnull Nov 09 '13 at 08:33
  • Yes, I see how the divmod method is working. I have write down the modulo method (x.modulo(y) means x-y*(x/y).floor) and understand it too. But why 13.div(-4) is not -3, as 13/-4 = -3.25? – gotqn Nov 09 '13 at 08:40
  • As I see from the documentation the div method "Uses / to perform division, then converts the result to an integer.". So, I suppose, when the result is negative number, it is rounded to the smaller number. In my case, -3.25 can be rounded to -3 or -4, -4 is smaller so it is being chosen. Could be this the case? – gotqn Nov 09 '13 at 08:45
  • @gotqn: Integer arithmetic and float rounding are not directly connected in the way you suppose. The float (or rational) rounding actually has a *different* choice to make, and different self-consistent behaviour to implement in a programming language. Not all languages implement integer division or rounding in the same way. I will try to add more details to answer. – Neil Slater Nov 09 '13 at 11:13