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)