用NaN对双打数组进行排序

Emm*_*l F 14 c# sorting nan .net-3.5

这更像是一个"你能解释这个"类型的问题,而不是其他任何问题.

我在工作中遇到了一个问题,我们在表中使用NaN值,但是当表被排序时,它以一种非常奇怪,奇怪的方式出现.我认为NaN正在捣乱,所以我写了一个测试应用程序来判断这是否属实.这就是我做的.

static void Main(string[] args)
{
    double[] someArray = { 4.0, 2.0, double.NaN, 1.0, 5.0, 3.0, double.NaN, 10.0, 9.0, 8.0 };

    foreach (double db in someArray)
    {
        Console.WriteLine(db);
    }

    Array.Sort(someArray);
    Console.WriteLine("\n\n");
    foreach (double db in someArray)
    {
        Console.WriteLine(db);
    }

    Console.ReadLine();
}
Run Code Online (Sandbox Code Playgroud)

结果如下:

之前:

4,2,NaN,1,5,3,NaN,10,9,8
Run Code Online (Sandbox Code Playgroud)

后:

1,4,NaN,2,3,5,8,9,10,NaN
Run Code Online (Sandbox Code Playgroud)

所以是的,NaN有些如何使排序的数组以奇怪的方式排序.

引用弗莱; "为什么这些东西?"

cor*_*iKa 10

我相信那是因为

a < NaN == false
a > NaN == false
a == NaN == false
Run Code Online (Sandbox Code Playgroud)

所以他们的比较分解了,这就抛出了整个排序.


小智 6

编辑(结论.最终结束.):这一个错误.

请参阅列表中包含double.NaN的列表<double/single> .Sort()[.NET35]中的错误报告错误,然后在为什么.NET 4.0对此数组的排序与.NET不同的情况下向Hans Passant进行投票.3.5?从中我撕开链接.

历史沉思

[参见文章:为什么.NET 4.0对此数组的排序与.NET 3.5不同?希望在这里可以找到关于这一特定问题的更有用的讨论.我也在那里交叉发布了这个回复.]

在.NET中由Phil4指出的行为是在CompareTo中定义的.请参阅.NET的double.CompareTo.这与.NET35中的行为相同,但根据方法文档,两个版本都应该保持一致...

Array.Sort(double[]):似乎没有CompareTo(double[])按预期使用,这可能是一个错误 - 请注意下面的Array.Sort(object [])和Array.Sort(double [])的区别.我想对以下内容进行澄清/更正.

在任何情况下,答案使用>,并<==解释为什么这些运营商不工作,但无法解释为什么Array.Sort会导致不可预测的输出.以下是我的一些调查结果,尽管它们可能很少.

首先,double.CompareTo(T)方法文档 - 根据文档很好地定义了这个顺序:

小于零:此实例小于值. - 或 - 此实例不是数字(NaN),值是数字.

:此实例等于值. - 或者 - 此实例和值都不是数字(NaN),PositiveInfinity或NegativeInfinity.

大于零:此实例大于值. - 或者 - 此实例是一个数字,值不是数字(NaN).

在LINQPad(3.5和4,两者都有相同的结果):

0d.CompareTo(0d).Dump();                  // 0
double.NaN.CompareTo(0d).Dump();          // -1
double.NaN.CompareTo(double.NaN).Dump();  // 0
0d.CompareTo(double.NaN).Dump();          // 1
Run Code Online (Sandbox Code Playgroud)

使用CompareTo(object)具有相同的结果:

0d.CompareTo((object)0d).Dump();                  // 0
double.NaN.CompareTo((object)0d).Dump();          // -1
double.NaN.CompareTo((object)double.NaN).Dump();  // 0
0d.CompareTo((object)double.NaN).Dump();          // 1
Run Code Online (Sandbox Code Playgroud)

所以这不是问题.

现在,从Array.Sort(object[])文档中 - 没有使用>,<==(根据文档) - 只是CompareTo(object).

使用Array IComparable的每个元素的实现对整个一维Array中的元素进行排序.

同样,Array.Sort(T[])用途CompareTo(T).

使用Array的每个元素的IComparable(Of T)泛型接口实现对整个Array中的元素进行排序.

让我们来看看:

LINQPad(4):

var ar = new double[] {double.NaN, 0, 1, double.NaN};
Array.Sort(ar);
ar.Dump();
// NaN, NaN, 0, 1
Run Code Online (Sandbox Code Playgroud)

LINQPad(3.5):

var ar = new double[] {double.NaN, 0, 1, double.NaN};
Array.Sort(ar);
ar.Dump();
// NaN, 0, NaN, 1
Run Code Online (Sandbox Code Playgroud)

LINQPad(3.5) - 注意阵列是对象,并且根据CompareTo合同"预期"行为.

var ar = new object[] {double.NaN, 0d, 1d, double.NaN};
Array.Sort(ar);
ar.Dump();
// NaN, NaN, 0, 1
Run Code Online (Sandbox Code Playgroud)

嗯.真.结论:

我不知道.

快乐的编码.