当我偶然发现一些非常有趣的东西时,我正在测试我的一些Ruby 1.9代码。我希望有人可以解释为什么会这样。
以下是代码:
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
这是输出:
X is NaN
Y is NaN
X and Y are both NaN.
This is all as we expected, but here is the mystery...
我已经以两种不同的方式为两个变量分配了一个NaN值,当我测试它们是否相同时,情况并非如此。之后我测试了一个变量是否与自身相等,甚至不是这样。期望某些价值等于自身是合乎逻辑的,但正如我们所能看到的那样,事实并非如此。
我不知道这是否是测试NaN值的正确方法,但我真的想知道所有这些背后的原因是什么让Ruby表现得像这样?
谢谢
答案 0 :(得分:5)
如果我们考虑一下,这似乎是合乎逻辑的。你从另一个无限大的数字中减去一个无限大的数字,得到x
?结果是什么?我们不知道。
我们如何比较我们不知道的事情?
要备份我的逻辑,这里是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;
}
答案 1 :(得分:3)
在Javascript中使用完全相同的代码:
x = Infinity - Infinity
y = 0/0
if(!(x==y)) alert("Not equal");
if(!(x==x)) alert("Not equal");
它将具有完全相同的行为。这种行为是预料之中的。两个NaN之间并不相同。无限 - 无限与[一个巨大的数字] - [同样巨大的数字]不同,它们是两个不同的巨大数字。没有人知道这次行动的结果。所以,这是一个NaN。
所以,这不是一个错误。这在数学上是合理的。
另外,试试
if(!(NaN==NaN)) alert("Not equal");
if(!(NaN===NaN)) alert("Not equal");
NaN永远不会等于任何东西。