对于double的比较,存在一些可能的坑,大家应该都清楚。比如容易注意的是double==double的精度问题。但是比较少注意的是double.NaN的比较


我们先看一个demo

public static void Main()
   {
      Console.WriteLine("NaN == NaN: {0}", Double.NaN == Double.NaN); 
      Console.WriteLine("NaN != NaN: {0}", Double.NaN != Double.NaN); 
      Console.WriteLine("NaN.Equals(NaN): {0}", Double.NaN.Equals(Double.NaN)); 
      Console.WriteLine("! NaN.Equals(NaN): {0}", ! Double.NaN.Equals(Double.NaN)); 
      Console.WriteLine("IsNaN: {0}", Double.IsNaN(Double.NaN));

      Console.WriteLine("\nNaN > NaN: {0}", Double.NaN > Double.NaN); 
      Console.WriteLine("NaN >= NaN: {0}", Double.NaN >= Double.NaN); 
      Console.WriteLine("NaN < NaN: {0}", Double.NaN < Double.NaN);
      Console.WriteLine("NaN < 100.0: {0}", Double.NaN < 100.0); 
      Console.WriteLine("NaN <= 100.0: {0}", Double.NaN <= 100.0); 
      Console.WriteLine("NaN >= 100.0: {0}", Double.NaN > 100.0);
      Console.WriteLine("NaN.CompareTo(NaN): {0}", Double.NaN.CompareTo(Double.NaN)); 
      Console.WriteLine("NaN.CompareTo(100.0): {0}", Double.NaN.CompareTo(100.0)); 
      Console.WriteLine("(100.0).CompareTo(Double.NaN): {0}", (100.0).CompareTo(Double.NaN)); 
   }

他的输出结果如下

NaN == NaN: False
NaN != NaN: True
NaN.Equals(NaN): True
! NaN.Equals(NaN): False
IsNaN: True

NaN > NaN: False
NaN >= NaN: False
NaN < NaN: False
NaN < 100.0: False
NaN <= 100.0: False
NaN >= 100.0: False
NaN.CompareTo(NaN): 0
NaN.CompareTo(100.0): -1
(100.0).CompareTo(Double.NaN): 1

我们可以看到,在相等性上,NaN!=NaN,但是可以使用NaN.Equals(NaN)判断相等性

而在<>符号比较上NaN都是返回false,使用CompareTo方法与其他double比较时,NaN都是返回-1

微软的考虑是NaN不是一个数值,因此不能参与数值比较(比如NaN+1=NaN,那么前后的NaN是否相等呢?)。

而方法的比较是为了满足如IComparable<double>接口的需要,便于排序等操作的使用

所以说有什么代码推荐呢?

  • 涉及可能会出现NaN的情况,需要使用double.IsNaN进行判断

  • 涉及double的比较判断,建议使用True条件。

    如判断a是否是正数,使用

    result=a>0?a:1
    

    而不使用

    result=a<=0?1:a
    

参考链接:

  • [Double Struct (System) Microsoft Docs](https://docs.microsoft.com/en-us/dotnet/api/system.double?view=netframework-4.7.2)

本文会经常更新,请阅读原文: https://huangtengxiao.gitee.io/post/%E5%B0%8F%E5%BF%83double%E7%9A%84%E6%AF%94%E8%BE%83.html ,以避免陈旧错误知识的误导,同时有更好的阅读体验。

知识共享许可协议 本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名黄腾霄(包含链接: https://huangtengxiao.gitee.io ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请 与我联系