отрицательный ноль в питоне - PullRequest
47 голосов
/ 03 ноября 2010

Я обнаружил отрицательный ноль в выводе из Python; например, он создан следующим образом:

k = 0.0
print(-k)

Вывод будет -0.0.

Однако, когда я сравниваю -k с 0.0 для равенства, это дает True. Есть ли какая-то разница между 0.0 и -0.0 (мне все равно, что они предположительно имеют различное внутреннее представление; меня интересует только их поведение в программе.) Есть ли какие-то скрытые ловушки, о которых я должен знать?

Ответы [ 5 ]

29 голосов
/ 03 ноября 2010

Проверить: −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 этого не делает.Когда умножение или деление включает в себя ноль со знаком, при вычислении знака ответа применяются обычные правила знака. </p>

Такие операции, как 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#924
  2. FPTAN в http://en.wikipedia.org/wiki/Atan2
  3. http://www.python.org/dev/peps/pep-0754/
15 голосов
/ 03 ноября 2010

Это имеет значение в функции 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
13 голосов
/ 16 августа 2014

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
11 голосов
/ 03 ноября 2010

Да, есть разница между 0,0 и -0,0 (хотя Python не позволяет мне воспроизводить его :-P).Если вы разделите положительное число на 0.0, вы получите положительную бесконечность;если вы разделите это же число на -0,0, вы получите отрицательную бесконечность.

Однако, кроме этого, между этими двумя значениями нет практической разницы.

1 голос
/ 14 марта 2014

Одинаковые значения, но разные числа

>>> 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#decimal.Decimal.compare http://docs.python.org/2/library/decimal.html#decimal.Decimal.compare_total

...