Project

General

Profile

Actions

Bug #10979

closed

Hash fails to distinguish 0.0 & -0.0

Added by avondrak (Alex Vondrak) almost 7 years ago. Updated over 6 years ago.

Status:
Closed
Priority:
Normal
Assignee:
-
Target version:
-
ruby -v:
ruby 2.2.0p0 (2014-12-25 revision 49005) [x86_64-darwin13]
[ruby-core:<unknown>]

Description

According to the docs ( http://ruby-doc.org/core-2.2.1/Hash.html ):

Two objects refer to the same hash key when their hash value is identical and the two objects are eql? to each other.

However, that does not appear to be the case for 0.0 and -0.0:

$ irb
2.2.0 :001 > (0.0).hash
 => -204267982040607835 
2.2.0 :002 > (-0.0).hash
 => -204267982040607835 
2.2.0 :003 > (0.0).eql?(-0.0)
 => true 
2.2.0 :004 > (-0.0).eql?(0.0)
 => true 
2.2.0 :005 > { 0.0 => :positive }.has_key?(-0.0)
 => false 
2.2.0 :006 > { -0.0 => :negative }.has_key?(0.0)
 => false 
2.2.0 :007 > { 0.0 => :positive }[-0.0]
 => nil 
2.2.0 :008 > { -0.0 => :negative }[0.0]
 => nil 
2.2.0 :009 > { 0.0 => :positive }.keys.map(&:hash)
 => [-204267982040607835] 
2.2.0 :010 > { -0.0 => :negative }.keys.map(&:hash)
 => [-204267982040607835]

I realize that floating point numbers are weird, and that 0.0 & -0.0 aren't literally the same machine representation. However, they are #eql? to each other have the same hash codes. I figure either the docs are misleading or there's a bug in the Hash primitives.

This also has carry-over effects to Array differences, for example:

$ irb
2.2.0 :001 > [0.0] - [-0.0]
 => [0.0] 
2.2.0 :002 > [-0.0] - [0.0]
 => [-0.0]
2.2.0 :003 > [0.0, -0.0] - [-0.0]
 => [0.0]

This was the initial behavior I observed in Ruby 2.1.3 that led me to file this bug. I tried Ruby 2.2.0 and the same behavior still seems to persist.

Actions #1

Updated by nobu (Nobuyoshi Nakada) almost 7 years ago

  • Backport changed from 2.0.0: UNKNOWN, 2.1: UNKNOWN, 2.2: UNKNOWN to 2.0.0: REQUIRED, 2.1: REQUIRED, 2.2: REQUIRED

Seems a bug because of FLONUM since 2.0.0.

Actions #2

Updated by nobu (Nobuyoshi Nakada) almost 7 years ago

  • Status changed from Open to Closed
  • % Done changed from 0 to 100

Applied in changeset r49999.


hash.c: same hash values with Float#hash

  • hash.c (rb_any_hash): use same hash values with Float#hash so that -0.0 and +0.0 will be identical. [ruby-core:68541] [Bug #10979]

Updated by nagachika (Tomoyuki Chikanaga) over 6 years ago

  • Backport changed from 2.0.0: REQUIRED, 2.1: REQUIRED, 2.2: REQUIRED to 2.0.0: REQUIRED, 2.1: REQUIRED, 2.2: DONE

Backported into ruby_2_2 branch at rr50619.

Updated by usa (Usaku NAKAMURA) over 6 years ago

  • Backport changed from 2.0.0: REQUIRED, 2.1: REQUIRED, 2.2: DONE to 2.0.0: REQUIRED, 2.1: DONE, 2.2: DONE

ruby_2_1 r50655 merged revision(s) 49999,50000.

Actions

Also available in: Atom PDF