I was testing some of mine Ruby 1.9 code when I've stumbled across something that is very interesting. I'm hoping that someone can explain why is this happening.
Here is the code:
inf = Float::INFINITY
x = inf - inf
y = 0.0/0.0
puts "X is #{x}"
puts "Y is #{y}"
puts "X and Y are both NaN." if x.nan? && y.nan?
puts "This is all as we expected, but here is the mystery..."
puts "X is not equal to Y." if x == y
puts "Surprisingly not even X is equal to X." if x == x
And this is the output:
X is NaN
Y is NaN
X and Y are both NaN.
This is all as we expected, but here is the mystery...
I have assigned a NaN value in two different ways to two variables and when I've tested if they were equal that was not the case. After that I've tested if one variable is equal to itself and even that wasn't true. It's logical to expect that some value is equal to itself but as we can se, it just isn't.
I don't know if this is the right way to test NaN values, but I would really like to know what is behind all of this and is there a reason for a Ruby to behave like this?
Thank you
If we think about it, it seems logical. You get x
by subtracting one infinitely large number from another infinitely large number? What's the result of that? We don't know.
How can we compare things that we don't know?
To backup my logic, here's the source of Float#==
static VALUE flo_eq(VALUE x, VALUE y)
{
volatile double a, b;
switch (TYPE(y)) {
case T_FIXNUM:
b = (double)FIX2LONG(y);
break;
case T_BIGNUM:
b = rb_big2dbl(y);
break;
case T_FLOAT:
b = RFLOAT_VALUE(y);
#if defined(_MSC_VER) && _MSC_VER < 1300
if (isnan(b)) return Qfalse;
#endif
break;
default:
return num_equal(x, y);
}
a = RFLOAT_VALUE(x);
#if defined(_MSC_VER) && _MSC_VER < 1300
if (isnan(a)) return Qfalse;
#endif
return (a == b)?Qtrue:Qfalse;
}
Make the exact same code in Javascript:
x = Infinity - Infinity
y = 0/0
if(!(x==y)) alert("Not equal");
if(!(x==x)) alert("Not equal");
It will have the exact same behavior. And this behavior is expected. Two NaN's are not equal between themselves. Infinity - Infinity is not the same thing as [One huge number] - [The same huge number], they are two different huge numbers. Nobody knows the result of this operation. So, this is a NaN.
So, this is not a mistake. This is mathematically plausible.
Also, try
if(!(NaN==NaN)) alert("Not equal");
if(!(NaN===NaN)) alert("Not equal");
NaN will never be equal to anything.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With