Python Infinity - любые предостережения?
Итак, Python имеет положительную и отрицательную бесконечность:
float("inf"), float("-inf")
Это просто похоже на тип функции, которая должна иметь некоторые предостережения. Есть ли что-нибудь я должен знать?
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.0
2.- при делении (в том числе по модулю) положительной или отрицательной бесконечности на положительную или отрицательную бесконечность результат не определен, поэтому
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.