Math.Max(1f, float.NaN) == NaN
new[] { 1f, float.NaN }.Max() == 1f
为什么?
编辑:同样的问题也有双倍!
答案 0 :(得分:5)
他还在this后续推文中解释了原因:
这是因为扩展方法使用(并记录使用)IComparable的实现,它将任何内容与>进行比较。为NaN。
答案 1 :(得分:4)
正如其他人发布的那样,我发布了一个类型的“为什么” - 因为它正在使用IComparable
作为记录。
这只会导致另一个“为什么”。特别是:
Console.WriteLine(Math.Max(0, float.NaN)); // Prints NaN
Console.WriteLine(0f.CompareTo(float.NaN)); // Prints 1
第一行表明NaN被认为大于0.第二行表明0被认为大于NaN。 (当然,这些都不能报告“这种比较没有意义”的结果。)
这看似不寻常,但这是正确的答案。如果所有元素都是NaN,则数组的max()为NaN。见IEEE 754r。
此外,Math.Max使用IEEE 754r总排序谓词,该谓词指定NaN与其他人的相对排序。
答案 2 :(得分:2)
(正确的)答案的一个补充说明:即使您只阅读简单的解释,两者都表现得有记录。
此IEnumerable上的Max()扩展名:
返回a中的最大值 单值序列。
和Math.Max():
[返回]参数val1或val2, 以较大者为准。如果val1,val2或 val1和val2都等于NaN, NaN被退回。
请注意,NaN不是值 - 因此可枚举的Max总是返回最大的值。 Math.Max返回两个值中较大的一个,如果其中一个或两个都是NaN,则返回NaN。
答案 3 :(得分:1)
如果您将NaN作为参数传递,Math.max方法专门用于返回NaN。请注意,这意味着Math.max(a,b)可以返回一个不大于任一参数的值; NaN与任何运算符相比,任何其他值都会产生错误。
在数组上使用.Max()时,默认实现(我相信)会扫描列表,查找比任何其他值更大的值。由于NaN从不比任何东西都要好,因此函数不会选择它。
简而言之,我认为你的问题的答案是Math.Max很奇怪,而扩展方法Max正确的做法。
答案 4 :(得分:0)
其他人已经发布了John发布的答案(扩展方法使用IComparable返回任何>然后是NaN),并使用反射器查看Math.Max的实现显示了这个
public static double Max(double val1, double val2)
{
if (val1 > val2)
{
return val1;
}
if (double.IsNaN(val1))
{
return val1;
}
return val2;
}
所以你可以看出为什么他们会返回不同的结果。如果你运行(1.0> double.NaN),它将返回false。
答案 5 :(得分:0)
我认为1或Nan是否更大并不是由任何标准定义的,因此由实现决定这一点。请注意,所有这些语句都会产生错误:
Console.WriteLine("1>Nan {0}]", 1.0 > double.NaN);
Console.WriteLine("1<Nan {0}]", 1.0 < double.NaN);
Console.WriteLine("1>=Nan {0}]", 1.0 >= double.NaN);
Console.WriteLine("1<=Nan {0}]", 1.0 <= double.NaN);
因此,如果Max()
定义为:
if (a<=b) return b else return a;
如果任何参数为none,它将返回。
if (a>b) return a else return b;
而且,如果任何参数是Nan,那么正确实现max总是返回b。