1

考虑以下使用 C/C++ 对复数执行操作的代码float

float real_part = log(3.f);
float imag_part = 0.f;

float real_part2 = (imag_part)*(imag_part)-(real_part*real_part);
float imag_part2 = (imag_part)*(real_part)+(real_part*imag_part);

结果将是

real_part2= -1.20695 imag_part2= 0
angle= 3.14159

其中angle是复数的相位,在这种情况下,是pi

现在考虑以下代码:

float real_part = log(3.f);
float imag_part = 0.f;

float real_part2 = (-imag_part)*(-imag_part)-(real_part)*(real_part);
float imag_part2 = (-imag_part)*(real_part)+(real_part)*(-imag_part);

结果将是

real_part2= -1.20695 imag_part2= 0
angle= -3.14159

结果的虚部使结果-0的相位为-pi

尽管仍然使用复数的主要参数和浮点的有符号属性来完成0,但是当定义复数的函数时,这种变化是一个问题。例如,如果sqrt使用 de Moivre 公式定义复数,这会将结果的虚部的符号更改为错误的值。

如何处理这种影响?

4

1 回答 1

2

编辑:现在这个问题似乎是有道理的,这似乎是 Kahan 在他的文章Branch Cuts for Complex Elementary Functions中回答的那种问题:

通常,应直接执行结合实数和复数变量的混合模式算术,而不是先将实数强制为复数,以免零符号变得无信息;纯虚数与复变量的组合也是如此。以这种方式直接进行算术运算可以节省执行时间,否则这些时间会被浪费在操作零上。

换句话说,即使是 IEEE 754 标准的主要设计者也不知道在计算复数时如何使零的符号有意义,其中一些是从实数提升而来的。


回答最初的问题:

在您显示的计算中,我没有发现任何问题。

float imag_part = 0.f;

float imag_part2 = (-imag_part)*(real_part)+(real_part*imag_part);

这设置imag_part2-0. + 0.,这是+0.四舍五入到最近的。

complex_number3b.y=complex_number3a.x*complex_number3a.y+complex_number3a.y*complex_number3a.x;

这评估为-0. + -0.,其本身评估为-0.

你的两个计算是不等价的,他们不产生相同的结果是正常的。两个结果都符合IEEE 754 零符号规则

于 2013-10-28T22:57:03.720 回答