Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby language curious integer arithmetic : (-5/2) != -(5/2)

Tags:

integer

ruby

I spent some time on a quite simple task about splitting an array. Until I found that: 2 == 5/2 and -3 == -5/2. To get -2 I need to pull the minus out of the parentheses: -2 == -(5/2). Why does this happen? As I understand it, the result rounds to the smallest integer, but (-2.5).to_i == -2. Very curious.

# https://www.codewars.com/kata/swap-the-head-and-the-tail/train/ruby
# -5/2 != -(5/2)
def swap_head_tail a
  a[-(a.size/2)..-1] + a[a.size/2...-(a.size/2)] + a[0...a.size/2] 
end 
like image 258
Dmitry Dmitriev Avatar asked Sep 20 '19 15:09

Dmitry Dmitriev


1 Answers

Why does this happen?

It's not quite clear what kind of answer your are looking for other than because that is how it is specified (bold emphasis mine):

15.2.8.3.4 Integer#/

/(other)

  • Visibility: public
  • Behavior:
    • a) If other is an instance of the class Integer:
      • 1) If the value of other is 0, raise a direct instance of the class ZeroDivisionError.
      • 2) Otherwise, let n be the value of the receiver divided by the value of other. Return an instance of the class Integer whose value is the largest integer smaller than or equal to n.
        NOTE The behavior is the same even if the receiver has a negative value. For example, -5 / 2 returns -3.

As you can see, the specification even contains your exact example.

It is also specified in the Ruby/Spec:

it "supports dividing negative numbers" do
  (-1 / 10).should == -1
end

Compare this with the specification for Float#to_i (bold emphasis mine):

15.2.9.3.14 Float#to_i

to_i

  • Visibility: public
  • Behavior: The method returns an instance of the class Integer whose value is the integer part of the receiver.

And in the Ruby/Spec:

it "returns self truncated to an Integer" do
  899.2.send(@method).should eql(899)
  -1.122256e-45.send(@method).should eql(0)
  5_213_451.9201.send(@method).should eql(5213451)
  1.233450999123389e+12.send(@method).should eql(1233450999123)
  -9223372036854775808.1.send(@method).should eql(-9223372036854775808)
  9223372036854775808.1.send(@method).should eql(9223372036854775808)
end
like image 87
Jörg W Mittag Avatar answered Oct 22 '22 17:10

Jörg W Mittag