This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Title: Complex number representation round-trip doesn't work with signed zero values
Type: behavior Stage:
Components: Versions: Python 3.3
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: Nosy List: Eric Wieser, eric.smith, ezio.melotti, mark.dickinson, mjacob, skrah
Priority: normal Keywords:

Created on 2013-03-02 11:28 by mjacob, last changed 2022-04-11 14:57 by admin. This issue is now closed.

Messages (6)
msg183313 - (view) Author: Manuel Jacob (mjacob) * Date: 2013-03-02 11:28
When evaluating, signed zero complex numbers aren't recovered correctly.
>>> -0j
>>> (-0-0j)
>>> 0j

According to the representation can be used to recreate an object with the same value. Shouldn't this also be possible with complex numbers?

When using complex('...'), round-trip works correctly. While this can be used to recover the exact number, i find it confusing that complex('...') isn't the same as eval('...').
>>> complex('-0j')
>>> complex('(-0-0j)')
>>> complex('0j')
msg183342 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2013-03-02 19:17
This is not easy to avoid, I'm afraid, and it's a consequence of Python's usual rules for mixed-type arithmetic:  (-0-0j) is interpreted as 0 - (0.0 + 0.0j) --- that is, the 0j is promoted to a complex instance (by giving it zero real part) before the subtraction is performed.  Then the real part of the result is computed as 0.0 - 0.0, which is 0.0.  Note that the first 0.0 comes from converting the *integer* 0 to a complex number.  If you do -0.0-0.0j you'll see a different result:

>>> -0.0-0.0j
msg183343 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2013-03-02 19:18
An aside:  C99 gets around this problem by allowing an (optional) Imaginary type, separate from Complex.  Very few compilers support it, though.
msg374872 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2020-08-05 11:12
The issue of changing the complex repr came up again in #41485, which has been closed as a duplicate of this issue.

See also, where Guido says:

> BTW I don't want repr() of a complex number to use the complex(..., ...)
notation -- it's too verbose.

FWIW, I'd be +1 on changing the complex repr, but given Guido's opposition we're probably looking at a PEP to make that happen, and I don't have the bandwidth or the energy to push such a PEP through.
msg374873 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2020-08-05 11:13
Also related: #40269
msg374878 - (view) Author: Eric Wieser (Eric Wieser) Date: 2020-08-05 12:03
> BTW I don't want repr() of a complex number to use the complex(..., ...)

A compromise would be to only use this notation if signed zeros are involved.


Another option would be to use slightly unusual reprs for these complex numbers, which at least round-trip:

    def check(s, v):
        c = eval(s)
        # use string equality, because it's the easiest way to compare signed zeros
        cs = f"complex({c.real}, {c.imag})"
        vs = f"complex({v.real}, {v.imag})"
        assert vs == cs, f' expected {vs} got {cs}'

    check("-(0+0j)", complex(-0.0, -0.0))
    check("(-0.0-0j)", complex(-0.0, 0.0))  # non-intuitive
    check("-(-0.0-0j)", complex(0.0, -0.0))  # non-intuitive

Which I suppose would extend to complex numbers containing just one signed zero

    check("(-0.0-1j)", complex(-0.0, -1))
    check("-(0.0-1j)", complex(-0.0, 1))
    check("-(1+0j)", complex(-1, -0.0))
    check("-(-1+0j)", complex(1, -0.0))

Only two of these reprs are misleading for users who don't understand what's going on, the rest will just strike users as odd.
Date User Action Args
2022-04-11 14:57:42adminsetgithub: 61538
2020-08-05 12:03:02Eric Wiesersetnosy: + Eric Wieser
messages: + msg374878
2020-08-05 11:14:17mark.dickinsonlinkissue40269 superseder
2020-08-05 11:13:18mark.dickinsonsetmessages: + msg374873
2020-08-05 11:12:17mark.dickinsonsetmessages: + msg374872
2020-08-05 11:10:32mark.dickinsonlinkissue41485 superseder
2013-03-02 19:18:11mark.dickinsonsetmessages: + msg183343
2013-03-02 19:17:11mark.dickinsonsetstatus: open -> closed
resolution: not a bug
messages: + msg183342
2013-03-02 12:49:24eric.smithsetnosy: + eric.smith
2013-03-02 11:30:19ezio.melottisetnosy: + mark.dickinson, ezio.melotti, skrah
2013-03-02 11:28:04mjacobcreate