20

我想知道 Python (3.3.0) 打印复数的方式。我正在寻找解释,而不是更改打印的方法。

例子:

>>> complex(1,1)-complex(1,1)
0j

为什么它不只打印“0”?我的猜测是:保持复杂类型的输出。

下一个例子:

>>> complex(0,1)*-1
(-0-1j)

好吧,一个简单的“-1j”或“(-1j)”就可以了。为什么是“-0”?这不是和+0一样吗?这似乎不是一个四舍五入的问题:

>>> (complex(0,1)*-1).real == 0.0
True

当虚部变为正数时,-0 消失:

>>> complex(0,1)
1j
>>> complex(0,1)*-1
(-0-1j)
>>> complex(0,1)*-1*-1
1j

还有一个例子:

>>> complex(0,1)*complex(0,1)*-1
(1-0j)
>>> complex(0,1)*complex(0,1)*-1*-1
(-1+0j)
>>> (complex(0,1)*complex(0,1)*-1).imag
-0.0

我在这里错过了什么吗?

4

4 回答 4

18

它打印0j表明它仍然是一个complex值。您也可以用这种方式输入它:

>>> 0j
0j

其余的可能是IEEE 754 浮点表示法的神奇结果,它区分了 0 和 -0,即所谓的有符号零。基本上,有一个位表示数字是正数还是负数,而不管数字是否恰好为零。这解释了为什么1j * -1给出一个负零实部的东西:正零乘以 -1。

标准要求 -0 比较等于 +0,这解释了为什么(1j * -1).real == 0.0仍然成立。

Python 仍然决定打印 -0 的原因是,在复杂的世界中,这些对分支切割产生了影响,例如在函数phase

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

这是关于虚部,而不是实部,但很容易想象实部的符号会产生类似差异的情况。

于 2012-11-14T21:56:38.910 回答
4

答案在于 Python 源代码本身。

我将使用您的一个示例。让

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

当你这样做时,a*b你正在调用这个函数

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

如果你在 python 解释器中这样做,你会得到

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

从 IEEE754,你得到一个负零,因为那不是 +0,你在打印时得到括号和实部。

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. */
...

我猜想(但我不确定)其基本原理来自使用基本复数函数计算时该符号的重要性(维基百科文章中有关带符号的零对此有参考)。

于 2012-11-14T22:11:24.847 回答
2
  • 0j是一个虚构的文字,它确实表示一个复数而不是整数或浮点数。

  • ( +-0"signed zero") 是 Python 符合IEEE 754 浮点表示结果,因为在 Python 中,complex根据定义是一对浮点数。由于后者,也不需要为 a 打印或指定零分数部分complex

  • 打印-0部分是为了准确地将内容表示文档要求(每当操作结果输出到控制台时都会隐式调用)。repr()repr()

  • 关于为什么(-0+1j) = 1j但是的问题(1j*-1) = (-0+1j) 请注意,(-0+0j)or(-0.0+0j)不是单个复数,而是表达式- 将int/float添加到complex. 为了计算结果,首先将第一个数字转换为complex( -0->(0.0,0.0)因为整数没有带符号的零,-0.0-> (-0.0,0.0))。然后它的.real.imag添加到相应的1j(+0.0,1.0)。结果是(+0.0,1.0):^) 。要直接构造复合体,请使用complex(-0.0,1).

于 2012-11-15T00:54:07.937 回答
1

就第一个问题而言:如果它只是打印出来0,它在数学上是正确的,但你不会知道你正在处理一个complex对象与一个int. 只要你不指定.real,你总是会得到一个 J 组件。

我不知道你为什么会得到-0;这在技术上并不正确(-1 * 0 = 0),但在语法上很奇怪。

至于其余部分,奇怪的是它并不一致,但是在技术上没有一个是正确的,只是实现的一个工件。

于 2012-11-14T21:59:44.530 回答