negative zero in python

PythonFloating PointFloating AccuracyZero

Python Problem Overview


I encountered negative zero in output from python; it's created for example as follows:

k = 0.0
print(-k)

The output will be -0.0.

However, when I compare the -k to 0.0 for equality, it yields True. Is there any difference between 0.0 and -0.0 (I don't care that they presumably have different internal representation; I only care about their behavior in a program.) Is there any hidden traps I should be aware of?

Python Solutions


Solution 1 - Python

Check out −0 (number) in Wikipedia

Basically IEEE does actually define a negative zero.

And by this definition for all purposes:

-0.0 == +0.0 == 0

I agree with aaronasterling that -0.0 and +0.0 are different objects. Making them equal (equality operator) makes sure that subtle bugs are not introduced in the code.
Think of 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
>>> 

[Edit: More info based on comments]

When I said for all practical purposes, I had chosen the word rather hastily. I meant standard equality comparison.

As the reference says, the IEEE standard defines comparison so that +0 = -0, rather than -0 < +0. Although it would be possible always to ignore the sign of zero, the IEEE standard does not do so. When a multiplication or division involves a signed zero, the usual sign rules apply in computing the sign of the answer.

Operations like divmod and atan2 exhibit this behavior. In fact, atan2 complies with the IEEE definition as does the underlying "C" lib.

>>> 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

One way is to find out through the documentation, if the implementation complies with IEEE behavior . It also seems from the discussion that there are subtle platform variations too.

However this aspect (IEEE definition compliance) has not been respected everywhere. See the rejection of PEP 754 due to disinterest! I am not sure if this was picked up later.

See also What Every Computer Scientist Should Know About Floating-Point Arithmetic.

Solution 2 - Python

math.copysign() treats -0.0 and +0.0 differently, unless you are running Python on a weird platform:

> math.copysign(x, y)
>      Return x with the sign of y. On a platform that supports signed zeros, copysign(1.0, -0.0) returns -1.0.

>>> import math
>>> math.copysign(1, -0.0)
-1.0
>>> math.copysign(1, 0.0)
1.0

Solution 3 - Python

It makes a difference in the atan2() function (at least, in some implementations). In my Python 3.1 and 3.2 on Windows (which is based on the underlying C implementation, according to the note CPython implementation detail near the bottom of the Python math module documentation):

>>> 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

Solution 4 - Python

Yes, there is a difference between 0.0 and -0.0 (though Python won't let me reproduce it :-P). If you divide a positive number by 0.0, you get positive infinity; if you divide that same number by -0.0 you get negative infinity.

Beyond that, though, there is no practical difference between the two values.

Solution 5 - Python

Same values, yet different numbers

>>> 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

Reference :
http://docs.python.org/2/library/decimal.html#decimal.Decimal.compare http://docs.python.org/2/library/decimal.html#decimal.Decimal.compare_total

Solution 6 - Python

To generalise or summarise the other answers, the difference in practice seems to come from calculating functions that are discontinued at 0 where the discontinuity is coming from a 0 division. Yet, python defines a 0 division as an error. So if anything is calculated with python operators, you can simply consider -0.0 as +0.0 and nothing to worry from. On the contrary, if the function is calculated by a built in function or a library that is written in another language, such as C, the 0 division may be defined otherwise in that language and may give different answers for -0.0 and 0.0.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionmaxView Question on Stackoverflow
Solution 1 - PythonpyfuncView Answer on Stackoverflow
Solution 2 - PythonAlex TrebekView Answer on Stackoverflow
Solution 3 - PythonCraig McQueenView Answer on Stackoverflow
Solution 4 - PythonChris Jester-YoungView Answer on Stackoverflow
Solution 5 - PythonuserView Answer on Stackoverflow
Solution 6 - PythonSamuel Châtelain-lacasseView Answer on Stackoverflow