Отрицательный ноль в python
[Python 3.1]
Я столкнулся с отрицательным нолем в выводе из python; он создается, например, следующим образом:
k = 0.0
print(-k)
Выход будет -0.0
.
Однако, когда я сравниваю -k
с 0.0 для равенства, он дает True. Есть ли разница между 0.0
и -0.0
(мне все равно, что у них, по-видимому, есть другое внутреннее представление, я только забочусь о их поведении в программе.) Есть ли скрытые ловушки, о которых я должен знать?
Ответы
Ответ 1
Отъезд: - 0 (число) в Википедии
В основном IEEE фактически определяет отрицательный нуль
И этим определением для всех целей:
-0.0 == +0.0 == 0
Я согласен с aaronasterling, что -0.0 и +0.0 - разные объекты. Составляя их равными (оператор равенства), убедитесь, что в коде не введены тонкие ошибки.
Подумайте о * 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" lib. См. Ссылку №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) из-за незаинтересованности! Я не уверен, что это было подобрано позже.
ссылки:
Ответ 2
Это влияет на функцию atan2()
(по крайней мере, в некоторых реализациях). В моем Python 3.1 и 3.2 в Windows (который основан на базовой реализации C, в соответствии с примечанием детализации реализации CPython рядом с bottom документации модуля 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
Ответ 3
Да, разница между 0.0 и -0.0 (хотя Python не позволит мне воспроизвести ее: -P). Если вы разделите положительное число на 0.0, вы получите положительную бесконечность; если вы разделите это же число на -0.0, вы получите отрицательную бесконечность.
Кроме того, между этими двумя значениями нет практической разницы.
Ответ 4
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
Ответ 5
Те же значения, но разные числа
>>> 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