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.
Created on 2015年12月11日 08:44 by Mark Lundeberg, last changed 2022年04月11日 14:58 by admin. This issue is now closed.
| Messages (6) | |||
|---|---|---|---|
| msg256209 - (view) | Author: Mark Lundeberg (Mark Lundeberg) | Date: 2015年12月11日 08:44 | |
Although -0.0 and +0.0 compare as equal using the == operator, they are distinct floating point numbers and in some cases behave differently. (See more information on the wikipedia article "Signed zero".) The distinction between +0.0 and -0.0 is most important in complex arithmetic, for example it is conventional and useful that sqrt(-1+0i) ==> +i and sqrt(-1-0i) ==> -i. Python currently allows the floating point number -0.0 to be entered as a literal:
>>> -0.0
-0.0
Complex floating point numbers in python also can hold negative zero components, as shown in their repr()
>>> -(1+0j)
(-1-0j)
However they cannot be input directly as literals; it is currently necessary to use the above construction. Unfortunately the output of the repr() cannot be used as a string literal to obtain the same number:
>>> (-1-0j)
(-1+0j)
except, in contrast:
>>> complex('-1-0j')
(-1-0j)
The literal -1-0j should yield a complex number with negative zero imaginary part. Note also that complex literals with negative zero real parts have the same bug, e.g. -0+1j is not the same as -(0-1j)
|
|||
| msg256210 - (view) | Author: STINNER Victor (vstinner) * (Python committer) | Date: 2015年12月11日 08:53 | |
You should use complex(a, b) to have a reliable behaviour.
Python parse doesn't see "-1-0j" as a complex literal, but as (-1)-(0j): int-complex. Example with the AST output:
>>> ast.dump(ast.parse('-1-0j'))
'Module(body=[Expr(value=BinOp(left=UnaryOp(op=USub(), operand=Num(n=1)), op=Sub(), right=Num(n=0j)))])'
It looks like complex has the same behaviour than float:
>>> x=-0.0; x=0+x; x.real
0.0
>>> x=-0.0; x=0-x; x.real
0.0
>>> x=complex(0.0, -0.0); x=0+x; (x.real, x.imag)
(0.0, 0.0)
>>> x=complex(0.0, -0.0); x=0-x; (x.real, x.imag)
(0.0, 0.0)
zero sign is lost on int+complex, int-complex, int+complex, int-complex.
|
|||
| msg256211 - (view) | Author: Mark Lundeberg (Mark Lundeberg) | Date: 2015年12月11日 09:01 | |
Good point, it is doing (int-complex), observe also the following pecularities: >>> -0 - 0j 0j >>> -0. - 0j (-0+0j) >>> -0j -0j >>> 0-0j 0j >>> -(0j) (-0-0j) >>> 0.+(-0j) 0j Does this mean the bug is in repr() ? As I understand the output of repr() is supposed to be something that can evaluated to recreate the same object. However I am unsure whether it would be nicer if repr() were to yield 'complex(-0.,-0.)' or '-(-0.+0j)'. |
|||
| msg256215 - (view) | Author: Mark Dickinson (mark.dickinson) * (Python committer) | Date: 2015年12月11日 14:43 | |
This is something that comes up repeatedly on the bug tracker. There's no bug here in the complex type or the repr. What there *is* is a limitation resulting from the fact that Python doesn't have *imaginary* literals, only *complex* literals. So in: -1-0j the 0j is already a complex number with both real and imaginary parts equal to 0.0. Then -1 gets promoted to a complex number with real part -1 and imaginary part 0.0. And now you're doing: complex(-1.0, 0.0) - complex(0.0, 0.0) which naturally gives an imaginary part of +0.0 rather than 0.0. You'll see the same issue in C: there was an attempt to fix it in C99 by introducing Imaginary types, but those Imaginary types haven't been widely adopted. The most recent reincarnation of the C standard finally introduces a macro that lets you instantiate a complex number in terms of its real and imaginary components (instead of doing real_part + imag_part * I); this is something that Python already has in the form of the complex constructor. Closing as not a bug. |
|||
| msg256216 - (view) | Author: Mark Dickinson (mark.dickinson) * (Python committer) | Date: 2015年12月11日 14:45 | |
> As I understand the output of repr() is supposed to be something that can evaluated to recreate the same object. Right, but that's an ideal that's not always achieved in practice. If I had my druthers, I'd 'fix' the repr of the complex object to return something that's written in terms of the constructor (for example, "complex(2.3, -0.0)"). I don't think that's a reasonable change from the POV of backwards compatibility though. |
|||
| msg256217 - (view) | Author: Mark Dickinson (mark.dickinson) * (Python committer) | Date: 2015年12月11日 14:48 | |
Previous discussions: #17336, #22548 |
|||
| History | |||
|---|---|---|---|
| Date | User | Action | Args |
| 2022年04月11日 14:58:24 | admin | set | github: 70026 |
| 2015年12月11日 14:48:51 | mark.dickinson | set | messages: + msg256217 |
| 2015年12月11日 14:45:35 | mark.dickinson | set | messages: + msg256216 |
| 2015年12月11日 14:43:14 | mark.dickinson | set | status: open -> closed resolution: not a bug messages: + msg256215 |
| 2015年12月11日 09:01:36 | Mark Lundeberg | set | messages: + msg256211 |
| 2015年12月11日 08:53:10 | vstinner | set | nosy:
+ mark.dickinson, vstinner messages: + msg256210 |
| 2015年12月11日 08:44:59 | Mark Lundeberg | create | |