1.0 == 1 versus eql? and equal?
Question
What is the return value of the following Ruby code?
1.0.eql?(1) # => false
1.0.equal?(1) # => false
1.0 == 1 # => ???
The correct answer is
-
trueCorrect -
false -
It raises
ArgumentError -
nil
Explanation
TL;DR
Ruby ships three distinct equality checks. == compares numeric values across types, so 1.0 == 1 returns true. eql? requires the same value and the same class, and equal? requires the very same object, which is why both return false for a Float and an Integer.
==: value equality
Numeric classes implement == with type conversion: an Integer and a Float are equal when they represent the same mathematical value.
1.0 == 1 # => true
1 == 1.0 # => true
eql?: value plus class
Float#eql? returns true only when the argument is also a Float with the same value. No numeric conversion happens.
1.0.eql?(1) # => false
1.eql?(1.0) # => false
1.0.eql?(1.0) # => true
This is the method Hash uses (together with #hash) to compare keys, so a Float key and an Integer key never collide:
h = { 1.0 => :float, 1 => :int }
h[1] # => :int
h[1.0] # => :float
equal?: object identity
equal? returns true only when both operands are the exact same object. 1.0 and 1 are different objects, so it returns false. Never override this method.
1.0.equal?(1) # => false
Edge cases
On 64-bit platforms small floats are flonums, immediate values encoded directly in the reference, just like small integers. Two occurrences of the same flonum are therefore the same object:
1.0.equal?(1.0) # => true
Do not rely on this for identity checks; it is an encoding detail, and larger floats are heap-allocated objects with distinct identities.
Share this quiz
Comments
No comments yet. Be the first.