Project

General

Profile

Actions

Bug #22452

open

`rb_equal` returns true for `NaN == NaN`

Bug #22452: `rb_equal` returns true for `NaN == NaN`

Added by byroot (Jean Boussier) 4 days ago. Updated 1 day ago.

Status:
Open
Assignee:
-
Target version:
-
[ruby-core:127157]

Description

I noticed this while trying to cleanup and simplify rb_equal.

>> Float::NAN == Float::NAN
=> false
>> [Float::NAN].index(Float::NAN)
=> 0

I would expect it to return nil.

Array#index is just an example, any core method, and even C extension relying on rb_equal is similarly impacted.

This bug is present on all Ruby versions, except for versions between 2.1 and 2.4.

The bug seem to have been re-introduced in 2.5 by 6e0e067de31511cebec01d176f628442371db879

JRuby seem to have the same behavior, but TruffleRuby correctly returnsnil.


Related issues 1 (0 open — 1 closed)

Related to Ruby - Bug #1720: [NaN] == [NaN] が true になるClosedmrkn (Kenta Murata)Actions

Updated by byroot (Jean Boussier) 4 days ago Actions #1

  • Description updated (diff)

Updated by byroot (Jean Boussier) 4 days ago Actions #2

  • Related to Bug #1720: [NaN] == [NaN] が true になる added

Updated by byroot (Jean Boussier) 4 days ago Actions #3 [ruby-core:127158]

Possibly a duplicate of [Bug #1720] where it was established that Float::NaN == Float::NaN is "undefined" therefore OK.

It seems that the motivation was to not prevent optimization of rb_equal.

Updated by Eregon (Benoit Daloze) 1 day ago · Edited Actions #4 [ruby-core:127177]

There is also equal?:

irb(main):003> RUBY_DESCRIPTION
=> "ruby 4.0.7 (2026-09-15 revision 229531a6cf) +PRISM [x86_64-linux]"
irb(main):001> Float::NAN == Float::NAN
=> false
irb(main):002> Float::NAN.equal?(Float::NAN)
=> true
irb(main):008> Float::NAN.equal?(-(0.0/0.0))
=> false
irb(main):009> Float::NAN.equal?(0.0/0.0)
=> false
irb(main):001> [Float::NAN, 0.0/0.0, -(0.0/0.0)].pack('d3').bytes.each_slice(8).to_a
=> [[0, 0, 0, 0, 0, 0, 248, 127], [0, 0, 0, 0, 0, 0, 248, 127], [0, 0, 0, 0, 0, 0, 248, 255]]

And on TruffleRuby:

irb(main):008> RUBY_DESCRIPTION
=> "truffleruby 40.0.0-dev-da7373fe (2026-09-03), like ruby 4.0.2, Oracle GraalVM Native [x86_64-linux]"
irb(main):003> Float::NAN == Float::NAN
=> false
irb(main):005> Float::NAN.equal?(Float::NAN)
=> true
irb(main):006> Float::NAN.equal?(-(0.0/0.0))
=> true
irb(main):007> Float::NAN.equal?(0.0/0.0)
=> false
irb(main):002> [Float::NAN, 0.0/0.0, -(0.0/0.0)].pack('d3').bytes.each_slice(8).to_a
=> [[0, 0, 0, 0, 0, 0, 248, 127], [0, 0, 0, 0, 0, 0, 248, 255], [0, 0, 0, 0, 0, 0, 248, 127]]

TruffleRuby compares the raw 64-bits of the double, for equal?.

(for I'm not sure what reason the NaN bit pattern is inverted for 0.0/0.0 and -(0.0/0.0), on CRuby and TruffleRuby/JRuby, maybe on C vs Java)

Actions

Also available in: PDF Atom