考虑以下代码使用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
的signed属性来完成,但当定义复数函数时,这种变化是个问题。例如,如果通过de Moivre公式定义复数的sqrt
,则会将结果的虚部符号更改为错误的值。
如何处理这种影响?
答案 0 :(得分: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 rules for the sign of zero。