New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
complex() on object with __complex__ function loses sign of zero imaginary part #73788
Comments
Consider the following simple class that provides a "__complex__" method. class C(object):
def __init__(self, x):
self.x = x
def __complex__(self):
return self.x
x=C(-0j) PYTHON 2.7.13
>>> x.x
-0j
>>> complex(x)
0j
PYTHON 3.6
>>> x.x
(-0-0j)
>>> complex(x)
(-0+0j) |
Confirmed on my machine. The effect of the source is to do |
Looking at the source, there's also an issue with complex subclasses here: >>> class C(complex):
... pass
...
>>> complex(C(-0j))
(-0+0j)
>>> complex(-0j)
(-0-0j) |
CPython 2.7 and 3.5 have issues with the sign of zeroes even without any custom class: >>> -(0j) # this is -(0+0j)
(-0-0j)
>>> (-0-0j) # but this equals to the difference between 0 and 0+0j
0j
>>> (-0.0-0j) # this is the difference between -0.0 and 0+0j
(-0+0j)
>>> -0j
-0j # <- on CPython 2.7
(-0-0j) # <- on CPython 3.5 It's unclear if the signs of the two potential zeroes in a complex number have a meaning, but the C standard considers these cases for all functions in the complex number's header. |
Armin: that's a separate issue, and is expected behaviour. >>> -(0j) # this is -(0+0j)
(-0-0j) Yes: 0j is complex(0.0, 0.0); negating negates both the real and imaginary parts. >>> (-0-0j) # but this equals to the difference between 0 and 0+0j
0j This is an operation between an integer (note that the initial negation is a no-op) and a complex. Here the integer gets promoted to complex(0.0, 0.0), and we do complex(0.0, 0.0) - complex(0.0, 0.0), which gives complex(0.0, 0.0). >>> (-0.0-0j) # this is the difference between -0.0 and 0+0j
(-0+0j) This is complex(-0.0, 0.0) - complex(0.0, 0.0). The real and imaginary parts are operated on separately, and in keeping with IEEE 754, the real part is evaluated as -0.0 - 0.0, which is -0.0. >>> -0j
-0j # <- on CPython 2.7
(-0-0j) # <- on CPython 3.5 The Python 3 behaviour here is correct. The Python 2 behaviour is the result of an unfortunate AST optimization designed to ensure that -<sys.maxint+1> is an int rather than a long. None of the above is a new issue. |
Yes, very much so. The signs are important in determining which side of a branch cut to use in the various cmath functions. |
Maybe I should be more explicit: what seems strange to me is that some complex numbers have a repr that, when entered in the source, produces a different result. For example, if you want the result |
IMHO it would be less surprising if repr(complex) would return 'complex(..., ...)': it would be possible to copy/paste and get the result value. I was bitten multiple time by the zero sign with complex numbers... |
Proposed patch fixes constructing complex from complex. But in future versions perhaps it is worth to disallow passing complex argument to two-arguments complex constructor. |
4 lines before the new "ci.real = cr.imag;", we have "cr.imag = 0.0; /* Shut up compiler warning */". The comment is now wrong: we really need to set cr.imag to 0.0. |
complex-constructor-from-complex2.patch looks good to me. What happens now? I presume we can no longer push to hg.python.org? So one of us needs to make a PR on GitHub and another review it? |
I pushed changes to my fork but when try to create a pull request it contains unrelated changes. Seems I do something wrong. |
Created #203, but I feel bad for having my name on the commits. :-( |
I'm a bit puzzled about where the commit 4ddd897 came from, but as far as I can tell the changes to 2.7, 3.5, 3.6 and master are all okay. All fixed. Thanks for the report! |
Misc/NEWS
so that it is managed by towncrier #552Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: