【问题标题】:Why is double.NaN not equal to itself?为什么 double.NaN 不等于自身?
【发布时间】:2010-11-11 20:09:27
【问题描述】:

谁能给我解释一下?在 C# 中 double.NaN 不等于 double.NaN

bool huh = double.NaN == double.NaN; // huh = false
bool huh2 = double.NaN >= 0; // huh2 = false
bool huh3 = double.NaN <= 0; // huh3 = false

我可以将什么常数与 double.NaN 进行比较并得到正确的结果?

【问题讨论】:

  • 只是为了解释你的胡说:NaN 等于没有,甚至不等于它本身。这是根据定义。 en.wikipedia.org/wiki/NaN
  • 我认为不幸的是上下文丢失了。如果我们有两个双精度数,并且都被赋值为 NaN 以表示实际值 1/0。它们应该相等,但由于上下文丢失,它们被视为不相等
  • 数学上正确。为什么有人会认为一个 nan 会等于另一个? sqrt( -1 ) != 1/0
  • 就像SQL中的NULL
  • @MichaelMeadows 1/0 是 Inf,而不是 NaN。

标签: c# .net


【解决方案1】:

如果你好奇,这就是Double.IsNaN 的样子:

public static bool IsNaN(double d)
{
    return (d != d);
}

时髦吧?

【讨论】:

  • 这很奇怪。但话又说回来,NaN 的声明也是如此:public const double NaN = (double) 1.0 / (double) 0.0;
  • @Fredik, @Erich:除以零将给出 inf(或,+inf,-inf 基于操作数),0 / 0(除其他外)导致 NaN。 steve.hollasch.net/cgindex/coding/ieeefloat.html 有一张很好的表格,上面有特殊操作/结果
  • 为了增加混乱,object.Equals(double.NaN, double.NaN) 返回 true
  • @JimBalter 你说得对,我的评论是错误的:参考来源实际上是说public const double NaN = (double)0.0 / (double)0.0;link to the reference source。感谢您指出了这一点。另一方面:犯错和撒谎是完全不同的两件事
  • 不确定您发布时是否正确,但 IsNaN 今天是 defined differently
【解决方案2】:

使用Double.IsNaN

【讨论】:

    【解决方案3】:
    bool isNaN = Double.IsNaN(yourNumber)
    

    【讨论】:

      【解决方案4】:

      这种行为是故意的。 NaN 的原因是表示 不是数字,所以这对于很多东西来说都是一个包罗万象的东西。

      将某事物与 NaN 进行比较的正确方法是使用 IsNaN 函数。

      【讨论】:

        【解决方案5】:

        在这里使用Double.IsNan() 来测试是否相等。原因是 NaN 不是数字。

        【讨论】:

          【解决方案6】:

          有一个专门的功能:

          double.IsNan(huh);
          

          【讨论】:

            【解决方案7】:

            使用方法“Double.IsNaN(value)”来检查这种情况。

            【讨论】:

              【解决方案8】:

              实际上,您已经找到了检查 IEEE-754 浮点数是否为 NaN 的方法:它是唯一一个计算结果为 False 的浮点值(或值范围,因为有多个 NaN)如果与自身相比,即:

              bool isNaN(double v) {
                  return v != v;
              }
              

              在底层,Double.IsNaN 方法实际上可能会做同样的事情。您仍然应该使用它,因为对于不了解 FP 标准的任何人来说,这种行为都会非常令人惊讶。

              【讨论】:

                【解决方案9】:

                我们对 NaN 的唯一了解是它是“非数字”。这并不意味着它具有与其状态相关的值。例如:

                ∞ + (-∞) = NaN

                0/0 = NaN

                (∞ + (-∞)) (0/0)

                这里有一些 C# 来演示

                var infinity = 100d / 0;
                var negInfinity = -100d / 0;
                
                var notANumber = infinity + negInfinity;
                Console.WriteLine("Negative Infinity plus Infinity is NaN: {0}", double.IsNaN(notANumber));
                
                var notANumber2 = 0d / 0d;
                Console.WriteLine("Zero divided by Zero is NaN: {0}", double.IsNaN(notANumber2));
                
                Console.WriteLine("These two are not equal: {0}", notANumber == notANumber2);
                

                【讨论】:

                  【解决方案10】:

                  Double.NaN != Double.NaN的原因很简单:

                  您是否希望0/0Math.Sqrt(-3) 相同?和Math.Sqrt(-7)一样?

                  在我看来,C# 中存在一个错误,即 Equals() 没有被 NaN 覆盖。

                  Assert.IsTrue(Double.NaN != Double.NaN);
                  Assert.IsTrue(Double.NaN.Equals(Double.NaN));
                  

                  同时

                  Assert.IsTrue(Double.PositiveInfinity == Double.NegativeInfinity);
                  Assert.IsTrue(Double.PositiveInfinity.Equals(Double.PositiveInfinity));
                  // same for Double.NegativeInfinity and Single
                  

                  DoubleSingle 使用静态函数,例如

                  Double.IsNaN(value) && Double.IsInfinity(value);
                  

                  或更具体:

                  Double.IsPositiveInfinity(value);
                  Double.IsNegativeInfinity(value);
                  

                  【讨论】:

                    【解决方案11】:

                    Equality 运算符认为两个 NaN 值彼此不相等。通常,Double 运算符不能用于将 Double.NaN 与其他 Double 值进行比较,尽管比较方法(例如 EqualsCompareTo)可以。看下面的例子

                    引用自msdn

                    class Program
                    {
                        static void Main(string[] args)
                        {
                            Double i = Double.NaN;
                            while (!i.Equals(i)) //this would be result in false
                            //while(i != i) // this would result in true.
                            {
                                Console.WriteLine("Hello");
                            }
                        }
                    }
                    

                    here 是 .net 小提琴。

                    【讨论】:

                      猜你喜欢
                      • 2012-02-07
                      • 1970-01-01
                      • 2011-09-16
                      • 2011-11-10
                      • 2021-04-29
                      • 2016-08-03
                      • 2011-07-09
                      相关资源
                      最近更新 更多