正如其他人所发表的,我在推特上发布了一个关于“为什么”的问题——因为它使用了文档中记录的 IComparable
接口。
然而,这只是另一个“为什么”的引子。具体来说:
Console.WriteLine(Math.Max(0, float.NaN)); // Prints NaN
Console.WriteLine(0f.CompareTo(float.NaN)); // Prints 1
这可能看起来不寻常,但这是正确的答案。如果数组中所有元素都是NaN,则数组的max()也是NaN。参见IEEE 754r。
此外,Math.Max使用IEEE 754r总序谓词,指定NaN与其他值的相对顺序。
在正确答案的基础上,还有一个补充:即使只阅读简单说明,两者行为均符合文档。
针对此 IEnumerable 的 Max() 扩展:
返回序列中的 Single 值的最大值。
而 Math.Max():
返回参数 val1 或 val2 中较大的那个。如果 val1、val2 或 val1 和 val2 都等于 NaN,则返回 NaN。
请注意,NaN 不是一个值 - 因此可枚举的 Max 总是返回最大的 value。Math.Max 返回两个值中较大的那个,如果其中任何一个或两个都是 NaN,则返回 NaN。
Math.max方法是专门设计的,如果您将NaN作为参数传递,则返回NaN。请注意,这意味着Math.max(a, b)可能返回一个不大于任何一个参数的值;NaN与任何其他值的任何运算符比较都会得到false。
在数组上使用.Max()时,默认实现(我认为)扫描列表,寻找比任何其他值更大的值。由于NaN永远不会比任何东西更大,因此函数不会选择它。
简而言之,我认为您问题的答案是Math.Max很奇怪,而扩展方法Max则做得很好。
其他人已经发布了约翰发布的答案(该扩展方法使用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。
我认为1和NaN哪个更大并没有被任何标准定义,所以这取决于实现来决定。请注意,所有这些语句都会产生false:
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,则它将返回a。
if (a>b) return a else return b;
而且,如果任何一个参数为 NaN,则 max 的正确实现总是返回 b。
Max
وک¯ç”±Enumerable
وڈگن¾›çڑ„é’ˆه¯¹IEnumerable<T>
çڑ„و‰©ه±•و–¹و³•ï¼Œه®ƒه¹¶ن¸چو¥è‡ھن؛ژArray
م€‚ - Anthony Pegram