Отрицательный ноль в питоне
[Python 3.1]
Я столкнулся с отрицательным нулем в выводе из Python; например, он создан следующим образом:
k = 0.0
print(-k)
Выход будет -0.0
,
Тем не менее, когда я сравниваю -k
0,0 для равенства, это дает True. Есть ли разница между 0.0
а также -0.0
(Мне все равно, что они предположительно имеют различное внутреннее представление; меня интересует только их поведение в программе.) Есть ли какие-то скрытые ловушки, о которых я должен знать?
7 ответов
Выезд: −0 (число) в Википедии
В основном IEEE фактически определяет отрицательный ноль
И по этому определению для всех целей:
-0.0 == +0.0 == 0
Я согласен с aaronasterling, что -0.0 и +0.0 - это разные объекты. Делая их равными (оператор равенства), вы гарантируете, что в коде не появятся тонкие ошибки. Подумайте о a * b == c * d
>>> a = 3.4
>>> b =4.4
>>> c = -0.0
>>> d = +0.0
>>> a*c
-0.0
>>> b*d
0.0
>>> a*c == b*d
True
>>>
[Редактировать: Больше информации на основе комментариев]
Когда я сказал для всех практических целей, я выбрал слово довольно поспешно. Я имел в виду стандартное сравнение на равенство.
Я хотел бы добавить больше информации и ссылок в этом отношении:
(1) Как говорится в ссылке, стандарт IEEE определяет сравнение так, что +0 = -0, а не -0 <+0. Хотя всегда можно было бы игнорировать знак нуля, стандарт IEEE этого не делает. Когда умножение или деление включает в себя подписанный ноль, при вычислении знака ответа применяются обычные правила знака.
Такие операции, как divmod, atan2, демонстрируют такое поведение. Фактически, atan2 соответствует определению IEEE, как и базовая библиотека "C". См. Ссылку № 2 для определения.
>>> divmod(-0.0,100)
(-0.0, 0.0)
>>> divmod(+0.0,100)
(0.0, 0.0)
>>> math.atan2(0.0, 0.0) == math.atan2(-0.0, 0.0)
True
>>> math.atan2(0.0, -0.0) == math.atan2(-0.0, -0.0)
False
Один из способов - узнать через документацию, соответствует ли реализация поведению IEEE. Из обсуждения также видно, что существуют и тонкие вариации платформы.
Однако этот аспект (соответствие определению IEEE) не всегда соблюдался. Смотрите отказ от PEP 754 (#3) из-за незаинтересованности! Я не уверен, что это было подобрано позже.
Рекомендации:
math.copysign()
лечит -0.0
а также +0.0
иначе, если вы не используете Python на странной платформе:
math.
Copysign (X, Y)
Вернуть x со знаком y. На платформе, которая поддерживает подписанные нули,copysign(1.0, -0.0)
возвращается-1.0
,
>>> import math
>>> math.copysign(1, -0.0)
-1.0
>>> math.copysign(1, 0.0)
1.0
Это имеет значение в atan2()
функция (по крайней мере, в некоторых реализациях). В моих Python 3.1 и 3.2 для Windows (который основан на базовой реализации C, согласно примечанию ореализации CPython в нижней части Python math
модульная документация):
>>> import math
>>> math.atan2(0.0, 0.0)
0.0
>>> math.atan2(-0.0, 0.0)
-0.0
>>> math.atan2(0.0, -0.0)
3.141592653589793
>>> math.atan2(-0.0, -0.0)
-3.141592653589793
Да, есть разница между 0.0 и -0.0 (хотя Python не позволит мне воспроизвести его:-P). Если вы разделите положительное число на 0.0, вы получите положительную бесконечность; если вы разделите это число на -0.0, вы получите отрицательную бесконечность.
Кроме того, между этими двумя значениями нет практической разницы.
Если вы когда-нибудь беспокоитесь о том, чтобы столкнуться с условием -0.0, просто добавьте + 0. к уравнению. Это не влияет на результаты, но переводит нули в положительное плавающее значение.
import math
math.atan2(-0.0, 0.0)
Out[2]: -0.0
math.atan2(-0.0, 0.0) + 0.
Out[3]: 0.0
Те же значения, но разные числа
>>> Decimal('0').compare(Decimal('-0')) # Compare value
Decimal('0') # Represents equality
>>> Decimal('0').compare_total(Decimal('-0')) # Compare using abstract representation
Decimal('1') # Represents a > b
Ссылка:
http://docs.python.org/2/library/decimal.html http://docs.python.org/2/library/decimal.html
Чтобы обобщить или обобщить другие ответы, разница на практике, по-видимому, связана с вычислением функций, которые прерываются в 0, где разрыв происходит из-за деления на 0. Тем не менее, Python определяет деление на 0 как ошибку. Поэтому, если что-то рассчитывается с помощью операторов Python, вы можете просто считать -0,0 как +0,0 и не о чем беспокоиться. Напротив, если функция вычисляется встроенной функцией или библиотекой, написанной на другом языке, таком как C, деление 0 может быть определено в этом языке иначе и может давать разные ответы для -0,0 и 0,0.