Searching for NaN in arrays behave oddly

arr = [0, Float::NAN, 1]
    arr.include?(Float::NAN) # => true
    arr.find_index(Float::NAN) # => nil

According to documentation both `Array#include?` and `Array#find_index`
should use `Object#==` to compare against array elements, but as we see it
doesn't happen (`#include?` doesn't use `#==` as `NaN != NaN`). It should
be fixed either in definition or in documentation.

···

--
Łukasz Niemier <lukasz@niemier.pl>
http://lukasz.niemier.pl

I am quite sure that this is a bug. Thanks for bringing it into account.

···

-----------------
Regards,
Arup Rakshit

-----Original Message-----
From: "Łukasz Niemier" <lukasz@niemier.pl>
Sent: ‎30-‎12-‎2014 18:27
To: "Ruby" <ruby-talk@ruby-lang.org>
Subject: Searching for NaN in arrays behave oddly

    arr = [0, Float::NAN, 1]
    arr.include?(Float::NAN) # => true
    arr.find_index(Float::NAN) # => nil

According to documentation both `Array#include?` and `Array#find_index` should use `Object#==` to compare against array elements, but as we see it doesn't happen (`#include?` doesn't use `#==` as `NaN != NaN`). It should be fixed either in definition or in documentation.

--

Łukasz Niemier <lukasz@niemier.pl>

http://lukasz.niemier.pl

According to documentation buggy is `Array#include?` but IMHO expected is
that behaviour. I would suggest to change comparator to `Object#eql?` and
change it to detect NaNs.

···

2014-12-30 14:11 GMT+01:00 Arup Rakshit <aruprakshit@rocketmail.com>:

I am quite sure that this is a bug. Thanks for bringing it into account.

-----------------
Regards,
Arup Rakshit
------------------------------
From: Łukasz Niemier <lukasz@niemier.pl>
Sent: ‎30-‎12-‎2014 18:27
To: Ruby <ruby-talk@ruby-lang.org>
Subject: Searching for NaN in arrays behave oddly

    arr = [0, Float::NAN, 1]
    arr.include?(Float::NAN) # => true
    arr.find_index(Float::NAN) # => nil

According to documentation both `Array#include?` and `Array#find_index`
should use `Object#==` to compare against array elements, but as we see it
doesn't happen (`#include?` doesn't use `#==` as `NaN != NaN`). It should
be fixed either in definition or in documentation.

--
Łukasz Niemier <lukasz@niemier.pl>
http://lukasz.niemier.pl

--
Łukasz Niemier <lukasz@niemier.pl>
http://lukasz.niemier.pl

I've tried this in MRI Ruby 1.8.7, 1.9.3, 2.0.0 and 2.1.5 from the
Ruby Microsoft Windows Installer.
The versions earlier than 2.1.5 give me:
  arr = [0, Float::NAN, 1]
  arr.include?(Float::NAN) # => true
  arr.find_index(Float::NAN) # => 1
and it's only in 2.1.5 that arr.find_index(Float::NAN) # => nil,
so I agree with Arup Rakshit that this definitely looks like a bug.

Unless it's an intentional change, but in that case, as you observed
in your first post, the behaviour of Array#include? and
Array#find_index would be inconsistent.

If only to remind myself, this link has a good explanation of why, as
you pointed out in your first post,
NaN != NaN
and why Python - and I suspect any language using Floating Point
Numbers as defined by IEEE - also have
NaN != NaN

I was a member of the IEEE-754 committee, I'll try to help clarify
things a bit. ... My understanding from talking to Kahan is that NaN
!= NaN originated out of two pragmatic considerations ... To be blunt:
the result of NaN == NaN isn’t going to change now. Better to learn to
live with it than to complain on the internet. ...

···

On 12/30/14, Łukasz Niemier <lukasz@niemier.pl> wrote:

According to documentation buggy is `Array#include?` but IMHO expected is
that behaviour. I would suggest to change comparator to `Object#eql?` and
change it to detect NaNs.

2014-12-30 14:11 GMT+01:00 Arup Rakshit <aruprakshit@rocketmail.com>:

I am quite sure that this is a bug. Thanks for bringing it into account.

-----------------
Regards,
Arup Rakshit
------------------------------
From: Łukasz Niemier <lukasz@niemier.pl>
Sent: ‎30-‎12-‎2014 18:27
To: Ruby <ruby-talk@ruby-lang.org>
Subject: Searching for NaN in arrays behave oddly

    arr = [0, Float::NAN, 1]
    arr.include?(Float::NAN) # => true
    arr.find_index(Float::NAN) # => nil

According to documentation both `Array#include?` and `Array#find_index`
should use `Object#==` to compare against array elements, but as we see
it
doesn't happen (`#include?` doesn't use `#==` as `NaN != NaN`). It should
be fixed either in definition or in documentation.

--
Łukasz Niemier <lukasz@niemier.pl>
http://lukasz.niemier.pl

--
Łukasz Niemier <lukasz@niemier.pl>
http://lukasz.niemier.pl

Another empirical data point: in MRI 2.2.0 (OS X) the behaviour is self-consistent with the idea that Float::NAN != Float::NAN.

[1] pry(main)> RUBY_VERSION
=> "2.2.0"
[2] pry(main)> arr = [0, Float::NAN, 1];
[3] pry(main)> arr.include?(Float::NAN)
=> false
[4] pry(main)> arr.find_index(Float::NAN)
=> nil
[5] pry(main)> Float::NAN == Float::NAN
=> false
[6] pry(main)> Float::NAN.nan?
=> true

···

On Dec 30, 2014, at 11:56 PM, Colin Bartlett <colinb2r@googlemail.com> wrote:

I've tried this in MRI Ruby 1.8.7, 1.9.3, 2.0.0 and 2.1.5 from the
Ruby Microsoft Windows Installer.
The versions earlier than 2.1.5 give me:
arr = [0, Float::NAN, 1]
arr.include?(Float::NAN) # => true
arr.find_index(Float::NAN) # => 1
and it's only in 2.1.5 that arr.find_index(Float::NAN) # => nil,
so I agree with Arup Rakshit that this definitely looks like a bug.

Unless it's an intentional change, but in that case, as you observed
in your first post, the behaviour of Array#include? and
Array#find_index would be inconsistent.

If only to remind myself, this link has a good explanation of why, as
you pointed out in your first post,
NaN != NaN
and why Python - and I suspect any language using Floating Point
Numbers as defined by IEEE - also have
NaN != NaN

http://stackoverflow.com/questions/1565164/what-is-the-rationale-for-all-comparisons-returning-false-for-ieee754-nan-values/1573715#1573715

I was a member of the IEEE-754 committee, I'll try to help clarify
things a bit. ... My understanding from talking to Kahan is that NaN
!= NaN originated out of two pragmatic considerations ... To be blunt:
the result of NaN == NaN isn’t going to change now. Better to learn to
live with it than to complain on the internet. ...

On 12/30/14, Łukasz Niemier <lukasz@niemier.pl> wrote:

According to documentation buggy is `Array#include?` but IMHO expected is
that behaviour. I would suggest to change comparator to `Object#eql?` and
change it to detect NaNs.

2014-12-30 14:11 GMT+01:00 Arup Rakshit <aruprakshit@rocketmail.com>:

I am quite sure that this is a bug. Thanks for bringing it into account.

-----------------
Regards,
Arup Rakshit
------------------------------
From: Łukasz Niemier <lukasz@niemier.pl>
Sent: ‎30-‎12-‎2014 18:27
To: Ruby <ruby-talk@ruby-lang.org>
Subject: Searching for NaN in arrays behave oddly

   arr = [0, Float::NAN, 1]
   arr.include?(Float::NAN) # => true
   arr.find_index(Float::NAN) # => nil

According to documentation both `Array#include?` and `Array#find_index`
should use `Object#==` to compare against array elements, but as we see
it
doesn't happen (`#include?` doesn't use `#==` as `NaN != NaN`). It should
be fixed either in definition or in documentation.

--
Łukasz Niemier <lukasz@niemier.pl>
http://lukasz.niemier.pl

--
Łukasz Niemier <lukasz@niemier.pl>
http://lukasz.niemier.pl

--

Mike Stok <mike@stok.ca>
http://www.stok.ca/~mike/

The "`Stok' disclaimers" apply.

Another empirical data point: in MRI 2.2.0 (OS X) the behaviour is self-consistent with the idea that Float::NAN != Float::NAN.

[1] pry(main)> RUBY_VERSION
=> "2.2.0"
[2] pry(main)> arr = [0, Float::NAN, 1];
[3] pry(main)> arr.include?(Float::NAN)
=> false
[4] pry(main)> arr.find_index(Float::NAN)
=> nil
[5] pry(main)> Float::NAN == Float::NAN
=> false
[6] pry(main)> Float::NAN.nan?
=> true

And the reason is, as Colin has pointed out:

irb(main):001:0> x = Float::NAN
=> NaN
irb(main):002:0> x == x
=> false
irb(main):003:0> x.eql? x
=> false
irb(main):004:0> x === x
=> false
irb(main):005:0> x.equal? x
=> true

···

On Wed, Dec 31, 2014 at 2:42 PM, Mike Stok <mike@stok.ca> wrote:

On Dec 30, 2014, at 11:56 PM, Colin Bartlett <colinb2r@googlemail.com> wrote:

If only to remind myself, this link has a good explanation of why, as
you pointed out in your first post,
NaN != NaN
and why Python - and I suspect any language using Floating Point
Numbers as defined by IEEE - also have
NaN != NaN

floating point - What is the rationale for all comparisons returning false for IEEE754 NaN values? - Stack Overflow

I was a member of the IEEE-754 committee, I'll try to help clarify
things a bit. ... My understanding from talking to Kahan is that NaN
!= NaN originated out of two pragmatic considerations ... To be blunt:
the result of NaN == NaN isn’t going to change now. Better to learn to
live with it than to complain on the internet. ...

Cheers

robert

--
[guy, jim].each {|him| remember.him do |as, often| as.you_can - without end}
http://blog.rubybestpractices.com/