On Fri, Oct 12, 2012 at 7:42 PM, Joshua Landau
Can you give me a more explicit example? When would you not *want* f(-0.0) to always return the result of f(0.0)? [aka, for -0.0 to warp into 0.0 on creation]
A few examples: (1) In the absence of exceptions, 1 / 0.0 is +inf, while 1 / -0.0 is -inf. So e.g. the function exp(-exp(1/x)) has different values at -0.0 and 0.0:
from numpy import float64, exp exp(-exp(1/float64(0.0))) 0.0 exp(-exp(1/float64(-0.0))) 1.0
(2) For the atan2 function, we have e.g.,
from math import atan2 atan2(0.0, -1.0) 3.141592653589793 atan2(-0.0, -1.0) -3.141592653589793
This gives atan2 a couple of nice invariants: the sign of the result always matches the sign of the first argument, and atan2(-y, x) == -atan2(y, x) for any (non-nan) x and y. (3) Similarly, for complex math functions (which aren't covered by IEEE 754, but are standardised in various other languages), it's sometimes convenient to be able to depend on invariants like e.g. asin(z.conj()) == asin(z).conj(). Those are only possible if -0.0 and 0.0 are distinguished; the effect is most visible if you pick values lying on a branch cut.
from cmath import sin z = complex(2.0, 0.0) asin(z).conjugate() (1.5707963267948966-1.3169578969248166j) asin(z.conjugate()) (1.5707963267948966-1.3169578969248166j)
You can't take that too far, though: e.g., it would be nice if complex multiplication had the property that (z * w).conjugate() was always the same as z.conjugate() * w.conjugate(), but it's impossible to keep both that invariant and the commutativity of multiplication. (E.g., consider the result of complex(1, 1) * complex(1, -1).) -- Mark