Jon Skeet berichtet heute (source), dass:Math.max vs Enumerable.Max
Math.Max(1f, float.NaN) == NaN
new[] { 1f, float.NaN }.Max() == 1f
Warum?
Edit: gleiche Ausgabe mit Doppel auch!
Jon Skeet berichtet heute (source), dass:Math.max vs Enumerable.Max
Math.Max(1f, float.NaN) == NaN
new[] { 1f, float.NaN }.Max() == 1f
Warum?
Edit: gleiche Ausgabe mit Doppel auch!
Wie andere geschrieben haben, twitterte ich eine Art von "warum" - in der es IComparable
wie dokumentiert verwendet.
Das führt nur zu einem anderen "warum" obwohl.Insbesondere:
Console.WriteLine(Math.Max(0, float.NaN)); // Prints NaN
Console.WriteLine(0f.CompareTo(float.NaN)); // Prints 1
Die erste Zeile zeigt, dass NaN als größer als 0 angesehen wird, In der zweiten Zeile zeigt, dass 0 als größer als NaN angesehen wird. (Beides kann berichten, das Ergebnis von „dieser Vergleich macht keinen Sinn“, natürlich.)
Ich habe den Vorteil, sehen die alle Antwort Tweets, natürlich einschließlich thesetwo:
Es mag ungewöhnlich erscheinen, aber das ist die richtige Antwort. max() eines Arrays ist NaN, wenn alle Elemente NaN sind. Siehe IEEE 754r.
Darüber hinaus verwendet Math.Max das IEEE 754r-Prädikat für die Gesamtordnung, das die relative Reihenfolge von NaN im Vergleich zu anderen angibt.
@john: danke John –
die Frage ist, sollte C# Team auf diese Art von unerwarteten Ergebnissen achten? –
@HPT: Das C# -Team hat nichts damit zu tun - es ist eine Bibliotheksfrage. Aber grundsätzlich vermute ich, dass die meisten Menschen (mich eingeschlossen) über eine ganze Reihe von Dingen über NaN überrascht sein würden. –
Er erklärte auch der Grund, warum in this Follow-up Tweet:
Es ist, weil die Erweiterung Methode verwendet die Implementierung von IComparable (und verwenden dokumentiert ist), die etwas als> NaN vergleicht.
Andere die Antwort geschrieben haben, dass John geschrieben (die Extension-Methode verwendet IComparable, die als etwas zurückgibt> dann NaN) und Reflektor bei der Umsetzung von Math.max aussehen zeigt diese
public static double Max(double val1, double val2)
{
if (val1 > val2)
{
return val1;
}
if (double.IsNaN(val1))
{
return val1;
}
return val2;
}
Sie können also sehen, warum sie unterschiedliche Ergebnisse zurückgeben. Wenn Sie (1.0> double.NaN) ausführen, wird false zurückgegeben.
Die Math.max-Methode wurde speziell entwickelt, um NaN zurückzugeben, wenn Sie NaN als Argument übergeben. Beachten Sie, dass dies bedeutet, dass es für Math.max (a, b) möglich ist, einen Wert zurückzugeben, der nicht größer als ein Argument ist. NaN verglichen mit irgendeinem Operator zu irgendeinem anderen Wert ergibt falsch.
Wenn Sie .Max() für das Array verwenden, scannt die Standardimplementierung (ich glaube) die Liste nach dem Wert durch, der größer als jeder andere Wert ist. Da NaN niemals größer als alles andere ist, wird es von der Funktion nicht ausgewählt.
Kurz gesagt, ich denke die Antwort auf Ihre Frage ist, dass Math.Max ist seltsam, während die Erweiterungsmethode Max es richtig macht.
Eine Ergänzung zu den (korrekten) Antworten: Beide verhalten sich wie dokumentiert, auch wenn Sie nur die einfache Erklärung lesen.
Max() Erweiterung auf dieser IEnumerable:
Gibt den Höchstwert in einer Sequenz von Single-Werten.
und Math.max():
[Rückgabe] Parameter val1 oder val2, je nachdem, was größer ist. Wenn val1, val2 oder sowohl val1 als auch val2 gleich NaN sind, wird NaN zurückgegeben.
Beachten Sie, dass NaN kein Wert ist - so die zählbare Max liefert immer den größten Wert . Math.Max gibt den größeren von zwei Werten zurück, oder NaN, wenn einer oder beide Werte NaN sind.
Ich nehme an, dass, ob 1 oder Nan ist größer ist nicht von jedem Standard definiert, so ist es der Umsetzung überlassen, dies zu entscheiden. Beachten Sie, dass alle diese Aussagen falsch erzeugen: wird
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);
Also, wenn Max()
wie folgt definiert:
if (a<=b) return b else return a;
es wird eine Rückkehr, wenn eines der Argumente keine ist.
Und das, auch korrekte Implementierung von Max immer zurück b wenn eines der Argumente ist Nan.
Link zu wo er dies meldet? –
@matt: sein Twitter-Account, @jonskeet –
'Max' ist eine von' Enumerable' bereitgestellte Erweiterungsmethode gegen 'IEnumerable', es kommt nicht von 'Array'. –