Format of complex number in Python

后端 未结 4 1616
清歌不尽
清歌不尽 2020-12-18 19:13

I am wondering about the way Python (3.3.0) prints complex numbers. I am looking for an explanation, not a way to change the print.

Example:

>>         


        
相关标签:
4条回答
  • 2020-12-18 19:42

    The answer lies in the Python source code itself.

    I'll work with one of your examples. Let

    a = complex(0,1)
    b = complex(-1, 0)
    

    When you doa*b you're calling this function:

    real_part = a.real*b.real - a.imag*b.imag
    imag_part = a.real*b.imag + a.imag*b.real
    

    And if you do that in the python interpreter, you'll get

    >>> real_part
    -0.0
    >>> imag_part
    -1.0
    

    From IEEE754, you're getting a negative zero, and since that's not +0, you get the parens and the real part when printing it.

    if (v->cval.real == 0. && copysign(1.0, v->cval.real)==1.0) {
        /* Real part is +0: just output the imaginary part and do not
           include parens. */
    ...
    else {
        /* Format imaginary part with sign, real part without. Include
           parens in the result. */
    ...
    

    I guess (but I don't know for sure) that the rationale comes from the importance of that sign when calculating with elementary complex functions (there's a reference for this in the wikipedia article on signed zero).

    0 讨论(0)
  • 2020-12-18 19:52
    • 0j is an imaginary literal which indeed indicates a complex number rather than an integer or floating-point one.

    • The +-0 ("signed zero") is a result of Python's conformance to IEEE 754 floating point representation since in Python, complex is by definition a pair of floating point numbers. Due to the latter, there's no need to print or specify zero fraction parts for a complex too.

    • The -0 part is printed in order to accurately represent the contents as repr()'s documentation demands (repr() is implicitly called whenever an operation's result is output to the console).

    • Regarding the question why (-0+1j) = 1j but (1j*-1) = (-0+1j). Note that (-0+0j) or (-0.0+0j) aren't single complex numbers but expressions - an int/float added to a complex. To compute the result, first the first number is converted to a complex (-0-> (0.0,0.0) since integers don't have signed zeros, -0.0-> (-0.0,0.0)). Then its .real and .imag are added to the corresponding ones of 1j which are (+0.0,1.0). The result is (+0.0,1.0) :^) . To construct a complex directly, use complex(-0.0,1).

    0 讨论(0)
  • 2020-12-18 19:54

    It prints 0j to indicate that it's still a complex value. You can also type it back in that way:

    >>> 0j
    0j
    

    The rest is probably the result of the magic of IEEE 754 floating point representation, which makes a distinction between 0 and -0, the so-called signed zero. Basically, there's a single bit that says whether the number is positive or negative, regardless of whether the number happens to be zero. This explains why 1j * -1 gives something with a negative zero real part: the positive zero got multiplied by -1.

    -0 is required by the standard to compare equal to +0, which explains why (1j * -1).real == 0.0 still holds.

    The reason that Python still decides to print the -0, is that in the complex world these make a difference for branch cuts, for instance in the phase function:

    >>> phase(complex(-1.0, 0.0))
    3.141592653589793
    >>> phase(complex(-1.0, -0.0))
    -3.141592653589793
    

    This is about the imaginary part, not the real part, but it's easy to imagine situations where the sign of the real part would make a similar difference.

    0 讨论(0)
  • 2020-12-18 20:01

    As far as the first question is concerned: if it just printed 0 it would be mathematically correct, but you wouldn't know you were dealing with a complex object vs an int. As long as you don't specify .real you will always get a J component.

    I'm not sure why you would ever get -0; it's not technically incorrect (-1 * 0 = 0) but it's syntactically odd.

    As far as the rest goes, it's strange that it isn't consistent, however none are technically correct, just an artifact of the implementation.

    0 讨论(0)
提交回复
热议问题