具有无穷大和 nan 的复数乘法/除法
complex multiplication / divison with infinity and nan
在真正的浮点运算中,我们有附加符号 INF(无穷大)、NAN 和带符号的零。对于复杂的算术,这更困难。如果使用 "naive" 乘法和除法规则
(a + ib)(c + id) = (ac - db) + i(ac+bd)
(a + ib)/(c + id) = ( (ac + db) + i(ac-bd) ) / (c*c + d*d)
对于 a、b、c、d 的一个变量为 INF 或 NAN 的几乎所有情况,都会出现错误 (*) 结果。
例如
- (1 + i0)*(INF + i0) = INF + iNAN 。与实数算术相比 1*INF = INF
- (0 + i1)* (NAN + i0) = NAN + iNAN。然而,人们会期望 i*NAN = (0+iNAN)
- 1 / (0+0i) = NAN + iNAN。这打破了例如 z = 1/(1/z),它在实际算术中完美运行。
这个列表很容易列出来。
问题是,如何正确实现复杂的除法和乘法,以便所有情况,包括当实部或虚部之一是 INF 和 NAN 时,都能给出有意义的结果?还有编程语言可以保证使用 INF 和 NAN 进行复杂运算的正确行为吗?
编辑:我想知道哪种编程语言标准(版本)确实需要使用 INF 和 NAN 进行正确的复数运算。我最感兴趣的语言是 C、C++ 和 FORTRAN 系列。
(*) 在数学上没有意义的意义上是错误的,或者在 IEEE-754 意义上是违反直觉的。
对于C,请查看C99或C11中的Annex G。至少 GCC 遵循这个,如果 clang 没有,我会感到惊讶。
对于 C++,IIRC C++ 标准已选择不包含 C99/C11 附件 G,复杂的算法 mult/div 取决于实现。
Fortran 标准没有指定必须如何实现复杂的乘法或除法。对于除法,GFortran 使用常见的 Smith (1962) 方法,除非指定了 -ffast-math,然后使用朴素算法。
有关计算复数除法的不同算法的比较,请参阅http://arxiv.org/abs/1210.4539
在真正的浮点运算中,我们有附加符号 INF(无穷大)、NAN 和带符号的零。对于复杂的算术,这更困难。如果使用 "naive" 乘法和除法规则
(a + ib)(c + id) = (ac - db) + i(ac+bd)
(a + ib)/(c + id) = ( (ac + db) + i(ac-bd) ) / (c*c + d*d)
对于 a、b、c、d 的一个变量为 INF 或 NAN 的几乎所有情况,都会出现错误 (*) 结果。
例如
- (1 + i0)*(INF + i0) = INF + iNAN 。与实数算术相比 1*INF = INF
- (0 + i1)* (NAN + i0) = NAN + iNAN。然而,人们会期望 i*NAN = (0+iNAN)
- 1 / (0+0i) = NAN + iNAN。这打破了例如 z = 1/(1/z),它在实际算术中完美运行。
这个列表很容易列出来。
问题是,如何正确实现复杂的除法和乘法,以便所有情况,包括当实部或虚部之一是 INF 和 NAN 时,都能给出有意义的结果?还有编程语言可以保证使用 INF 和 NAN 进行复杂运算的正确行为吗?
编辑:我想知道哪种编程语言标准(版本)确实需要使用 INF 和 NAN 进行正确的复数运算。我最感兴趣的语言是 C、C++ 和 FORTRAN 系列。
(*) 在数学上没有意义的意义上是错误的,或者在 IEEE-754 意义上是违反直觉的。
对于C,请查看C99或C11中的Annex G。至少 GCC 遵循这个,如果 clang 没有,我会感到惊讶。
对于 C++,IIRC C++ 标准已选择不包含 C99/C11 附件 G,复杂的算法 mult/div 取决于实现。
Fortran 标准没有指定必须如何实现复杂的乘法或除法。对于除法,GFortran 使用常见的 Smith (1962) 方法,除非指定了 -ffast-math,然后使用朴素算法。
有关计算复数除法的不同算法的比较,请参阅http://arxiv.org/abs/1210.4539