Jon Skeet сообщает сегодня (source), что:Math.max против Enumerable.Max
Math.Max(1f, float.NaN) == NaN
new[] { 1f, float.NaN }.Max() == 1f
Почему?
Редактировать: та же проблема с двойным также!
Jon Skeet сообщает сегодня (source), что:Math.max против Enumerable.Max
Math.Max(1f, float.NaN) == NaN
new[] { 1f, float.NaN }.Max() == 1f
Почему?
Редактировать: та же проблема с двойным также!
Как и другие, я написал твиттер один вид «почему» - в том, что он использует IComparable
как задокументировано.
Это просто приводит к другому «почему».В частности:
Console.WriteLine(Math.Max(0, float.NaN)); // Prints NaN
Console.WriteLine(0f.CompareTo(float.NaN)); // Prints 1
Первая строка указывает, что NaN рассматривается как больше 0. Вторая строка показывает, что 0 рассматривается как более NaN. (Ни один из них может сообщить результат «это сравнение не имеет смысла», конечно.)
У меня есть преимущество видеть все отклики твиты, конечно, в том числе thesetwo:
Это может показаться необычным, но это правильный ответ. max() массива NaN, если все элементы являются NaN. См. IEEE 754r.
Кроме того, Math.Max использует общий предикат порядка IEEE 754r, который определяет относительное упорядочение NaN и других.
@john: спасибо john –
вопрос должен ли C# команда позаботиться о таких неожиданных результатах? –
@ HPT: Команда C# не имеет к этому никакого отношения - это вопрос библиотеки. Но в принципе я подозреваю, что большинство людей (включая меня) были бы удивлены любым количеством вещей о NaN. –
Он также объяснил причину, почему в this последующих твиттере:
Это потому, что метод расширения использует (и документированные использовать) осуществление IComparable, который сравнивает ничего, как> NaN.
Другие опубликовали ответ, который отвечал Джон (метод расширения использует 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.
Метод Math.max специально разработан для возврата NaN, если вы передадите NaN в качестве аргумента. Обратите внимание, что это означает, что Math.max (a, b) может возвращать значение, не превышающее любой аргумент; NaN по сравнению с любым оператором для любого другого значения дает false.
При использовании .Max() в массиве реализация по умолчанию (я считаю) просматривает список, ищущий значение, которое сравнивается больше любого другого значения. Поскольку NaN никогда не сравнивается больше чем что-либо, он не будет выбран функцией.
Короче говоря, я думаю, что ответ на ваш вопрос заключается в том, что Math.Max странный, в то время как метод расширения Max делает все правильно.
Одно из утверждений (правильных) ответов: Оба ведут себя как задокументированные, даже если вы читаете простое объяснение.
Max() расширение на этом IEnumerable:
Возвращает максимальное значение в последовательности единичных значений.
и Math.max():
[Возврат] Параметр знач1 или знач2, в зависимости от того, больше. Если val1, val2 или оба значения val1 и val2 равны NaN, возвращается NaN.
Обратите внимание, что NaN не является значением - так перечислимы Макс всегда возвращает наибольшее значение . Math.Max возвращает большее из двух значений, или NaN, если один или оба из них являются NaN.
Я полагаю, что если 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;
будет возвращать, если какой-либо из аргументов нет.
if (a>b) return a else return b;
И это, также правильная реализация max всегда возвращает b, если любой из аргументов является Nan.
Ссылка на то, где он сообщает об этом? –
@matt: его учетная запись Twitter, @jonskeet –
'Max' - это метод расширения, предоставляемый' Enumerable' против 'IEnumerable', это не из 'Array'. –