Search code examples
pythonstringcomplex-numbersrepr

Bad string representation of negative imaginary numbers in Python


For some reason the string representation of negative imaginary numbers in Python is different for equal values:

>>> str(-3j)
'(-0-3j)'
>>> str(0-3j)
'-3j'

Moreover, if I try to get the string representation of -0-3j, I get:

>>> str(-0-3j)
'-3j'

Which seems like an inconsistency.

The problem is that I use the string representation of complex scalar tensors to compute the hash of some operators, and because of this inconsistency I get different hashes for equal operators.

Is there any way to convert '(-0-3j)' to '-3j'?

Edit:

Mechanic Pig pointed out that:

>>> str(-0.-3j)
'(-0-3j)'

Solution

  • This issue is filed as a bug and stimulated appearance of PEP-0682 - Format Specifier for Signed Zero and originates from Floating-point arithmetic limitations.

    Once the bug is resolved -0 will not scare unnecessarily any more. But until then...

    You can adapt the snippet from this answer:

    def real_norm(no):
        return no if no != 0 else abs(no)
        
    def imag_norm(ino):
        return complex(real_norm(ino.real), real_norm(ino.imag))
    
    test_cases = [-0-3j, 0-3j, -0-0j, 0-0j, -0+0j]
    for tc in test_cases:
        tn = imag_norm(tc)
        print(f"{tc} -> {tn}")