Ответы:
Вы все еще можете получить значения не числа (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 не выше и не ниже -infNaNложным ( infне выше и не ниже NaN)При сравнении на равенство +infи +infравны, как есть -infи -inf. Это очень обсуждаемый вопрос и может показаться спорным для вас, но это в стандарте IEEE и Python ведет себя так же , как это.
Конечно, +infэто неравно, -infи все, включая NaNсебя, неравны NaN.
Большинство вычислений с бесконечностью будут давать бесконечность, если только оба операнда не равны бесконечности, когда при делении операции, или по модулю, или при умножении на ноль, следует учитывать некоторые специальные правила:
NaN0.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.