Python Infinity - любые предостережения?


Итак, Python имеет положительную и отрицательную бесконечность:

float("inf"), float("-inf")

Это просто похоже на тип функции, которая должна иметь некоторые предостережения. Есть ли что-нибудь я должен знать?

4 164

4 ответа:

вы все еще можете получить значения not-a-number (NaN) из простой арифметики с участием inf:

>>> 0 * float("inf")
nan

обратите внимание, что вы обычно не получить inf значение через обычные арифметические вычисления:

>>> 2.0**2
4.0
>>> _**2
16.0
>>> _**2
256.0
>>> _**2
65536.0
>>> _**2
4294967296.0
>>> _**2
1.8446744073709552e+19
>>> _**2
3.4028236692093846e+38
>>> _**2
1.157920892373162e+77
>>> _**2
1.3407807929942597e+154
>>> _**2
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
OverflowError: (34, 'Numerical result out of range')

The inf значение считается очень особенным значением с необычной семантикой, поэтому лучше знать о OverflowError сразу через исключение, а не inf значение молча вводится в ваш проведенные расчеты.

реализация Python следует стандарт IEEE-754 довольно хорошо, который вы можете использовать в качестве руководства, но он опирается на базовую систему, на которой он был скомпилирован, поэтому платформа различий может произойти. Недавно было применено исправление, которое позволяет "бесконечность", а также "inf", но это здесь не так важно.

следующие разделы одинаково хорошо применимы к любому языку, реализующему IEEE floating точечная арифметика правильно, она не специфична только для Python.

сравнение на неравенство

когда имеешь дело с бесконечностью и больше > или меньше < операторы, следующие графы:

  • любое число, в том числе +inf выше -inf
  • любое число, в том числе -inf меньше +inf
  • +inf - это ни выше, ни ниже. чем +inf
  • -inf - это не выше и не ниже, чем -inf
  • ни в какое сравнение с участием NaN ложно (inf ни выше, ни ниже, чем NaN)

сравнение на равенство

при сравнении на равенство, +inf и +inf равны, как -inf и -inf. Это очень спорный вопрос и может показаться противоречивым, но это в стандарте IEEE и Python ведет себя так же, как что.

конечно, +inf не равно -inf и все, в том числе NaN сам по себе, неравен NaN.

расчеты с бесконечностью

большинство вычислений с бесконечностью даст бесконечность, если оба операнда не бесконечны, когда операция деления или по модулю, или с умножением на ноль, есть некоторые специальные правила, чтобы иметь в виду:

  • при умножении на ноль, для которого результат не определен, это дает NaN
  • при делении любого числа (кроме самой бесконечности) на бесконечность, что дает 0.0 или -0.02.
  • при делении (в том числе по модулю) положительной или отрицательной бесконечности на положительную или отрицательную бесконечность результат не определен, поэтому NaN.
  • при вычитании результаты могут быть удивительными, но следуйте общий математический смысл:
    • при выполнении inf - inf, результат не определен: NaN;
    • при выполнении inf - -inf, результат inf;
    • при выполнении -inf - inf, в результате -inf;
    • при выполнении -inf - -inf, результат не определен:NaN.
  • при добавлении, это может быть так же удивительно тоже:
    • при выполнении inf + inf, результат inf;
    • при выполнении inf + -inf, результат не определен:NaN;
    • при выполнении -inf + inf результат не определено:NaN;
    • при выполнении -inf + -inf, в результате -inf.
  • используя math.pow,pow или ** сложно, так как он не ведет себя так, как должен. Он выдает исключение переполнения, когда результат с двумя вещественными числами слишком высок, чтобы соответствовать поплавку двойной точности (он должен возвращать бесконечность), но когда вход inf или -inf, он ведет себя правильно и возвращает либо inf или 0.0. Когда второй аргумент NaN возвращает NaN, если первый аргумент 1.0. Есть еще вопросы, не все описано в документах.
  • math.exp страдает теми же проблемами, что и math.pow. Решение исправить это для переполнения-использовать код, подобный этому:

    try:
        res = math.exp(420000)
    except OverflowError:
        res = float('inf')
    

Примечания

Примечание 1: в качестве дополнительного предостережения, что, как определено стандартом IEEE, если ваш результат расчета ниже-или переполнения, результатом будет не ошибка под-или переполнения, а положительная или отрицательная бесконечность:1e308 * 10.0 доходность inf.

примечание 2: потому что любой расчет с NaN возвращает NaN и ни в какое сравнение с NaN, включая и false, вы должны использовать math.isnan функция, чтобы определить, если номер действительно NaN.

Примечание 3: хотя Python поддерживает запись float('-NaN'), знак игнорируется, потому что нет никакого знака на NaN внутренне. Если вы разделите -inf / +inf, результат NaN, а не -NaN (нет такого понятия).

примечание 4: будьте осторожны, чтобы полагаться на любой из вышеперечисленных, поскольку Python полагается на библиотеку C или Java, для которой он был скомпилирован, и не все базовые системы реализуют все это поведение правильно. Если вы хотите быть уверены, проверьте на бесконечность, прежде чем делать свои расчеты.

1) в последнее время означает так как версия 3.2.
2) плавающие точки поддерживают положительный и отрицательный нуль, так что:x / float('inf') сохраняет свой знак и -1 / float('inf') доходность -0.0,1 / float(-inf) доходность -0.0,1 / float('inf') доходность 0.0 и -1/ float(-inf) доходность 0.0. Кроме того, 0.0 == -0.0 и true, вы должны вручную проверить знак, если вы не хотите, чтобы это было правдой.

Так же как и C99.

представление с плавающей запятой IEEE 754, используемое всеми современными процессорами, имеет несколько специальных битовых шаблонов, зарезервированных для положительной бесконечности (знак=0, exp=~0, frac=0), отрицательной бесконечности (знак=1, exp=~0, frac=0) и многих NaN (не число: exp=~0, frac≠0).

Все, о чем вам нужно беспокоиться: некоторая арифметика может вызвать исключения/ловушки с плавающей точкой, но они не ограничиваются только этими "интересными" константами.

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

вычисление дроби по модулю бесконечности приводит к результату nan (Не число), вместо получения обычных результатов моддинга числа на бесконечность. Вот пример:

>>> from fractions import Fraction
>>> from math import inf
>>> 3 % inf
3.0
>>> 3.5 % inf
3.5
>>> Fraction('1/3') % inf
nan

Я подал вопрос на Python bug tracker. Это можно увидеть на https://bugs.python.org/issue32968.