复制 Python 的复数到字符串的转换

Replicate Python's complex-number-to-string conversion

import operator
>>> operator.truediv(-5.6, complex(-1, 0)) #eg1
(5.6-0j)
>>> operator.truediv(-5.6, complex(0, -1)) #eg2
(-0-5.6j)
>>> operator.truediv(-5.6, complex(0, 1)) #eg3
5.6j
>>> operator.truediv(-5.6, complex(1, 0)) #eg4
(-5.6+0j)
>>> operator.truediv(5.6, complex(0,-1)) #eg 5
(-0+5.6j)

有什么方法可以知道将复数转换为它在 Python 交互式解释器中出现的字符串表示形式的确切规则?喜欢一些,

  1. 在 eg1 中打印 0j 但在 eg3 中不打印。

  2. 有时会像 eg1 和 eg4

  3. 那样打印 0 , -0
  4. eg2 和 eg5.

我知道这没什么区别,但我想实现与 Python 完全相同的功能。我的意思是输出应该完全一样。

如有任何帮助,我们将不胜感激。 而且不是作业题,也感谢阅读

Python 将始终显示复数的虚部,否则您无法从输出中区分它确实是复数。这类似于在浮点数上包含 .0,即使它恰好是整数。

当不正好为+0时显示实部。在您提供的示例中,显示的是实部,因为它是负零。请注意,在浮点数中,负零和正零具有不同的表示,即使它们比较相等:

>>> float.fromhex('-0x0.0')
-0.0
>>> float.fromhex('0x0.0')
0.0
>>> float.fromhex('-0x0.0') == 0.0
True

这对模拟 Python 的输出可能没有太大帮助,因为您可能无法轻易预测 Python 何时会在其结果中得到负数 0。例如:

>>> neg0 = float.fromhex('-0x0.0')
>>> neg0
-0.0
>>> neg0+0j
0j

加法已将实部归一化为 +0

>>> neg0*1j
(-0+0j)
>>> 0.0*(-1j)
-0j

乘以正虚数会使实部保持负号,但乘以负虚数不会使实部为负。

但是所有这些都只是实现细节,因此 Python 的不同实现可能会有所不同。

浮点数具有正零和负零的两种独立表示这一事实是 IEEE 754 浮点实现的一个细节。参见 https://en.wikipedia.org/wiki/Signed_zero

源码中检测是否输出实部的部分包括:

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

第一部分对于两种形式的零都是正确的。第二部分仅当实部不是负数时才为真(copysign(x,y) 给出 x 的值,符号为 y,因此 copysign(1.0, negativezero) 将是 -1.

如果你想实现另一个程序来精确复制 CPython 解释器的当前行为,你可以研究复数表示的源代码:static PyObject * complex_repr (PyComplexObject *v)。该函数负责将复数默认转换为字符串。

一些细节可以在函数 PyAPI_FUNC(char *) PyOS_double_to_string (double val, char format_code, int precision, int flags, int *type) 中找到。

我不认为浮点数的确切交互输出是官方 Python 语言规范的一部分,所以源代码可能是这里最好的指南。


编辑:如果您不想重新发明轮子,可能是时候研究一下 embedding Python in another application