具有NaN值的变量在Ruby中不等于它自己

时间:2012-07-05 21:13:57

标签: ruby equality nan

当我偶然发现一些非常有趣的东西时,我正在测试我的一些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表现得像这样?

谢谢

2 个答案:

答案 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永远不会等于任何东西。