Обратите внимание, что константа 1e309будет интерпретироваться как +infи -1e309будет интерпретироваться как -inf.
Крис Тейлор
Ответы:
97
Вы все еще можете получить значения не числа (NaN) из простой арифметики inf:
>>>0* float("inf")
nan
Обратите внимание, что вы обычно не получите infзначение с помощью обычных арифметических вычислений:
>>>2.0**24.0>>> _**216.0>>> _**2256.0>>> _**265536.0>>> _**24294967296.0>>> _**21.8446744073709552e+19>>> _**23.4028236692093846e+38>>> _**21.157920892373162e+77>>> _**21.3407807929942597e+154>>> _**2Traceback(most recent call last):File"<stdin>", line 1,in?OverflowError:(34,'Numerical result out of range')
infЗначение считается очень особым значением с необычной семантикой, так что лучше знать о OverflowErrorсразу через исключение, а не имеющее infзначение молча впрыскивается в свои расчеты.
Простое сложение с плавающей точкой, умножение и т. Д., К счастью, даст inf: f = 1.3407807929942597e + 154; f * f => инф. Это скорее исключение **, чтобы вызвать ошибку OverflowError.
Эрегон
@eregon, на самом деле, **кажется немного глючит. Когда он переполняется действительными числами, он выдает ошибку, но когда любой из его операндов равен infили -inf, он возвращает либо 0.0или inf. Так что он работает правильно, когда ввод бесконечен, но не когда результат должен быть бесконечностью.
Авель
2
@Abel Это не глючит. Переполнение означает, что число очень велико. Слишком большой, чтобы представлять его, но все же намного меньше бесконечности. Помещение бесконечности в такое место может быть полезно для обработчика исключений вашей конкретной логики приложения, но в целом для Python будет некорректно.
Лутц Пречелт
6
@Lutz, если это произойдет как умножение, это все еще непоследовательное поведение. Конечно, большой * большой тоже не бесконечность.
Следующие разделы одинаково хорошо применимы к любому языку, который правильно реализует арифметику IEEE с плавающей запятой, он не специфичен только для Python.
Сравнение по неравенству
При работе с бесконечностью и операторами больше >или меньше <, учитываются следующие значения:
любое сравнение с 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)exceptOverflowError:
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
Эван Кралл
4
Вот почему я сказал, что это был маленький придурок. Вы на минуту меня беспокоили, что знак будет полностью игнорироваться при работе с бесконечностью, и я хотел уточнить для других людей.
Эван Кралл
12
Ну, почти: 1 / float ('бесконечность') == 0.0
Фил
3
@Phil: Хотя я почти уверен, что вы просто пытались показать, что не все вычисления с inf приводят к inf или NaN, я просто хотел дать понять другим, которые могут читать комментарии, что 1 / float ('infinity ') == 0.0 верно; поскольку, когда вы приближаетесь к бесконечности, результат деления приближается к 0. Я знаю, что это просто базовое исчисление, но я хотел убедиться, что читающие понимают или, по крайней мере, имеют представление о том, почему результат такой, какой он есть.
Энтони Пейс
1
У меня такое ощущение, что этот ответ намного лучше, чем принятый ответ.
Представление IEEE 754 с плавающей запятой, используемое всеми современными процессорами, имеет несколько специальных битовых комбинаций, зарезервированных для положительной бесконечности (знак = 0, exp = ~ 0, frac = 0), отрицательной бесконечности (знак = 1, exp = ~ 0, frac = 0 ) и много NaN (не число: exp = ~ 0, frac ≠ 0).
Все, что вам нужно беспокоиться: некоторая арифметика может вызывать исключения / ловушки с плавающей запятой, но они не ограничиваются только этими «интересными» константами.
Так что, если моя арифметика слишком большая, она может стать инфой?
Casebash
@ Casebash Нет, это вызовет OverflowError.
wizzwizz4
2
Я нашел оговорку, о которой никто до сих пор не упомянул. Я не знаю, будет ли это часто встречаться в практических ситуациях, но здесь это делается для полноты картины.
Обычно вычисление числа по бесконечности по модулю возвращает себя в виде числа с плавающей запятой, но возвращает бесконечность по модулю nan(не число). Вот пример:
>>>from fractions importFraction>>>from math import inf
>>>3% inf
3.0>>>3.5% inf
3.5>>>Fraction('1/3')% inf
nan
1e309
будет интерпретироваться как+inf
и-1e309
будет интерпретироваться как-inf
.Ответы:
Вы все еще можете получить значения не числа (NaN) из простой арифметики
inf
:Обратите внимание, что вы обычно не получите
inf
значение с помощью обычных арифметических вычислений: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
. Решение, чтобы исправить это для переполнения, состоит в том, чтобы использовать код, подобный этому:Ноты
Примечание 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
(не число). Вот пример:Я подал проблему на трекер ошибок Python. Это можно увидеть по адресу https://bugs.python.org/issue32968 .
Обновление: это будет исправлено в Python 3.8 .
источник
в
1/x
доле, доx = 1e-323
этого есть,inf
но когдаx = 1e-324
или мало он бросаетZeroDivisionError
так что будьте осторожны!
источник