Ответы:
Вы все еще можете получить значения не числа (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
значение молча впрыскивается в свои расчеты.
**
кажется немного глючит. Когда он переполняется действительными числами, он выдает ошибку, но когда любой из его операндов равен inf
или -inf
, он возвращает либо 0.0
или inf
. Так что он работает правильно, когда ввод бесконечен, но не когда результат должен быть бесконечностью.
Реализация языка Python следует стандарту IEEE-754 , очень хорошо, что вы можете использовать в качестве руководства, но она опирается на основной системе он был составлен на, так различие платформы может произойти. Недавно было применено исправление, которое допускает «бесконечность», а также «inf» , но здесь это не имеет большого значения.
Следующие разделы одинаково хорошо применимы к любому языку, который правильно реализует арифметику 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, для которой он был скомпилирован, и не все базовые системы правильно реализуют все это поведение. Если вы хотите быть уверенным, проверьте бесконечность, прежде чем делать свои вычисления.
Recently) В последнее время означает, что начиная с версии 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
, вы должны вручную проверить знак , если вы не хотите , чтобы это было правдой.
-1 * float('infinity') == -inf
Как и С99 .
Представление IEEE 754 с плавающей запятой, используемое всеми современными процессорами, имеет несколько специальных битовых комбинаций, зарезервированных для положительной бесконечности (знак = 0, exp = ~ 0, frac = 0), отрицательной бесконечности (знак = 1, exp = ~ 0, frac = 0 ) и много NaN (не число: exp = ~ 0, frac ≠ 0).
Все, что вам нужно беспокоиться: некоторая арифметика может вызывать исключения / ловушки с плавающей запятой, но они не ограничиваются только этими «интересными» константами.
OverflowError
.
Я нашел оговорку, о которой никто до сих пор не упомянул. Я не знаю, будет ли это часто встречаться в практических ситуациях, но здесь это делается для полноты картины.
Обычно вычисление числа по бесконечности по модулю возвращает себя в виде числа с плавающей запятой, но возвращает бесконечность по модулю 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 .
ОЧЕНЬ ПЛОХАЯ ПЕРЕДАЧА: Деление на ноль
в 1/x
доле, до x = 1e-323
этого есть, inf
но когда x = 1e-324
или мало он бросаетZeroDivisionError
>>> 1/1e-323
inf
>>> 1/1e-324
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ZeroDivisionError: float division by zero
так что будьте осторожны!
1e309
будет интерпретироваться как+inf
и-1e309
будет интерпретироваться как-inf
.