Python: встроенные функции max / min зависят от порядка параметров - PullRequest
48 голосов
/ 21 ноября 2010

max(float('nan'), 1) оценивается в нан

max(1, float('nan')) оценивается в 1

Это предполагаемое поведение?


Спасибо за ответы.

max вызывает исключение, когда итерация пуста.Почему бы max Python не вызывать исключение, когда присутствует nan?Или, по крайней мере, сделать что-нибудь полезное, например, вернуть nan или игнорировать nan.Текущее поведение очень небезопасно и кажется совершенно неразумным.

Я обнаружил еще более удивительное последствие такого поведения, поэтому я только что опубликовал связанный вопрос .

Ответы [ 3 ]

41 голосов
/ 21 ноября 2010
In [19]: 1>float('nan')
Out[19]: False

In [20]: float('nan')>1
Out[20]: False

Число с плавающей запятой nan не больше и не меньше целого числа 1. max начинается с выбора первого элемента и заменяет его только тогда, когда он находит элемент, который строго больше.

In [31]: max(1,float('nan'))
Out[31]: 1

Поскольку nan не больше 1, возвращается 1.

In [32]: max(float('nan'),1)
Out[32]: nan

Поскольку 1 не больше nan, возвращается nan.


PS. Обратите внимание, что np.max трактует float('nan') по-разному:

In [36]: import numpy as np
In [91]: np.max([1,float('nan')])
Out[91]: nan

In [92]: np.max([float('nan'),1])
Out[92]: nan

но если вы хотите игнорировать np.nan s, вы можете использовать np.nanmax:

In [93]: np.nanmax([1,float('nan')])
Out[93]: 1.0

In [94]: np.nanmax([float('nan'),1])
Out[94]: 1.0
8 голосов
/ 21 ноября 2010

Я не видел этого раньше, но это имеет смысл. Обратите внимание, что nan очень странный объект:

>>> x = float('nan')
>>> x == x
False
>>> x > 1
False
>>> x < 1
False

Я бы сказал, что поведение max в этом случае не определено - какой ответ вы ожидаете? Единственное разумное поведение - предполагать, что операции являются антисимметричными.


Обратите внимание, что вы можете воспроизвести это поведение, создав неработающий класс:

>>> class Broken(object):
...     __le__ = __ge__ = __eq__ = __lt__ = __gt__ = __ne__ =
...     lambda self, other: False
...
>>> x = Broken()
>>> x == x
False
>>> x < 1
False
>>> x > 1
False
>>> max(x, 1)
<__main__.Broken object at 0x024B5B50>
>>> max(1, x)
1
1 голос
/ 21 ноября 2010

Макс работает следующим образом:

Первый элемент задается как maxval, а затем следующий сравнивается с этим значением.Сравнение всегда будет возвращать False:

>>> float('nan') < 1
False
>>> float('nan') > 1
False

Так что, если первое значение равно nan, то (поскольку сравнение возвращает false), оно не будет заменено на следующем шаге.

OTOH, если1 - первое, то же самое происходит: но в этом случае, поскольку 1 было установлено, оно будет максимальным.

Вы можете проверить это в коде Python, просто посмотрите на функцию min_max в Python / bltinmodule..c

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...