Отрицательный ноль в питоне

[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) из-за незаинтересованности! Я не уверен, что это было подобрано позже.

Рекомендации:

  1. http://docs.sun.com/source/806-3568/ncg_goldberg.html
  2. FPTAN в http://en.wikipedia.org/wiki/Atan2
  3. http://www.python.org/dev/peps/pep-0754/

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.

Другие вопросы по тегам