Реализация 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, для которой он был скомпилирован, и не все базовые системы правильно реализуют все это поведение. Если вы хотите быть уверенным, проверьте на бесконечность перед выполнением ваших расчетов.
¹) В последнее время означает, что с версия 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
, вы должны вручную проверить знак, если не хотите, чтобы он был истинным.