2

Can anybody explain the below result of the division of a negative number:

2.6.1 :001 > -25/24
 => -2 
2.6.1 :002 > 25/24
 => 1 

Why is it -2 instead of -1?

More examples on weird behaviour:

2.6.1 :003 > 24/25
 => 0 
2.6.1 :004 > -24/25
 => -1 

Any ideas? Thank you.

belgoros
  • 3,590
  • 7
  • 38
  • 76
  • It's because the floor of `(-1 - 1/24)` equals `-2`. – Marek Lipka Jul 09 '19 at 13:03
  • 1
    Does it mean that Ruby always calls `#floor` under the hood in case of Integer division? And where does `(-1 - 1/24)` come from? – belgoros Jul 09 '19 at 13:06
  • 1
    Here is a more detailed explanation behind the behaviour: https://stackoverflow.com/a/19518866/1954610 – Tom Lord Jul 09 '19 at 14:36
  • 1
    @TomLord Wow, so there were some historical discussions like that, thanks a lot! After 10 years of Ruby, I've never asked myself about it until today :). – belgoros Jul 09 '19 at 14:44

4 Answers4

5

Different programming languages use different definitions for (negative) integer division. Ruby uses the one described by Knuth in Concrete Mathematics, p. 82.

It can be illustrated by an example: let's say we are working with weeks. Our weeks start on Sunday. Numbers are zero-based, so we begin at week 0, day 0:

----- 0 -----
0 1 2 3 4 5 6
S M T W T F S
^

If we move forward by 9 days, we are at week 1, day 2:

----- 0 -----   ----- 1 -----
0 1 2 3 4 5 6   0 1 2 3 4 5 6
S M T W T F S   S M T W T F S
                    ^

These values are returned by / and %:

9 / 7 #=> 1
9 % 7 #=> 2

If we move backward by 9 days (from 0), we are at week -2, day 5:

---- -2 -----   ---- -1 -----   ----- 0 -----
0 1 2 3 4 5 6   0 1 2 3 4 5 6   0 1 2 3 4 5 6
S M T W T F S   S M T W T F S   S M T W T F S
          ^

Using / and %:

-9 / 7 #=> -2
-9 % 7 #=> 5

There's a funny note on the margin of that page:

Beware of computer languages that use another definition.

Stefan
  • 109,145
  • 14
  • 143
  • 218
4

A way you can think about integer division is:

  1. You do the floating point division.
  2. You round the result down.

Hence:

(25.0 / 24.0).floor  # => 1
(-25.0 / 24.0).floor # => -2
ndnenkov
  • 35,425
  • 9
  • 72
  • 104
3

I could simply find desired functionality by using parenthesis,

-(25/24)
# => -1

Perhaps, why -25/24 surprised you:

For the actual values in float division provide you -1.041

Your result using integer division is being rounded down toward the more negative value of -2. This is also known as Floor division

ray
  • 5,454
  • 1
  • 18
  • 40
  • Pheu, this one just adds another one question: `-25/24 => -2`, but `(-25/24) => -1` – belgoros Jul 09 '19 at 13:30
  • @belgoros, nice question, I found answer in python doc. Please check edited answer. – ray Jul 09 '19 at 13:32
  • thank you. So my suggestion was correct about calling `#floor` at the end of every division under the hood? I didn't find any answer in Ruby docs. – belgoros Jul 09 '19 at 13:34
  • @belgoros, Yes it was all about floor to negative side :) – ray Jul 09 '19 at 13:36
  • 1
    @belgoros, it's all about precedence, so `-(25.0/24.0).floor` it's like `-((25.0/24.0).floor) #--> -(1)` – iGian Jul 09 '19 at 14:43
0

Interger division in Ruby returns floor or the floating point result of the division:

https://ruby-doc.org/core-2.6/Numeric.html#method-i-div

Uses / to perform division, then converts the result to an integer. Numeric does not define the / operator; this is left to subclasses.

Equivalent to num.divmod(numeric)[0].

And divmod uses floor: :

q = floor(x/y)
x = q*y + r
mrzasa
  • 22,895
  • 11
  • 56
  • 94