Python Infinity – есть какие-нибудь предостережения?

StackOverflow https://stackoverflow.com/questions/1628026

  •  06-07-2019
  •  | 
  •  

Вопрос

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

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

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

Это было полезно?

Решение

Вы все еще можете получить значения не числа (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')

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

Другие советы

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

Следующие разделы одинаково применимы к любому языку, который правильно реализует арифметику с плавающей запятой IEEE, это касается не только 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.0².
  • при делении (в том числе по модулю) положительной или отрицательной бесконечности на положительную или отрицательную бесконечность результат не определен, поэтому 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, включая NaN сам по себе false, вам следует использовать math.isnan функция, позволяющая определить, действительно ли число NaN.

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

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

¹) Недавно означает с тех пор, как версия 3.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 & # 8800; 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. Его можно увидеть по адресу https://bugs.python.org/issue32968 .

Обновление: это будет исправлено в Python 3.8 .

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top