【问题标题】:complex multiplication / divison with infinity and nan具有无穷大和 nan 的复数乘法/除法
【发布时间】:2016-09-05 02:28:52
【问题描述】:

在实数浮点运算中,我们有附加符号 INF(无穷大)、NAN 和有符号零。对于复杂的算术,这更加困难。如果一个人使用“幼稚”的乘法和除法规则

(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 的意义上是违反直觉的。

【问题讨论】:

  • 在什么情况下?什么语言? Here 是 clang 的 C++ <complex> 实现。如果您查看 operator * 实现,它会演示如何处理 INF/NaN。不同意什么?
  • 他们似乎做得对。感谢您的链接。我的问题是哪种语言可以保证它。即规范要求使用哪种语言正确的 INF 和 NAN 行为。据我所知,C++ 并非如此(但我可能是错的)。 FORTRAN 似乎也不需要它。在这里我想澄清一下。
  • 问题是,如果你想编写依赖于处理 INF 和 NAN 的可移植代码,如果一些编译器做对了,而另一些编译器做错了,那是毫无意义的。

标签: math floating-point ieee-754 complex-numbers


【解决方案1】:

对于 C,请查看 C99 或 C11 中的附录 G。至少 GCC 遵循这一点,如果 clang 没有,我会感到惊讶。

对于 C++,IIRC C++ 标准选择不包含 C99/C11 Annex G,复杂 mult/div 的算法由实现决定。

Fortran 标准没有规定必须如何实现复杂的乘法或除法。对于除法,GFortran 使用常见的 Smith (1962) 方法,除非指定了 -ffast-math,否则使用朴素算法。

不同算法计算复数除法的比较,请看http://arxiv.org/abs/1210.4539

【讨论】:

  • 这可能也很有趣:Claude-Pierre Jeannerod、Nicolas Louvet 和 Jean-Michel Muller,“关于使用 FMA 进行复杂浮点除法的分量精度”。在 第 21 届 IEEE 计算机算术研讨会 (ARITH 21) 中,2013 年 4 月 7 日,第 83-90 页 (online),以及:Douglas M. Priest,“高效缩放对于复杂的划分。” ACM 数学软件交易 (TOMS) 30.4 (2004): 389-401。 (online, paywall)
  • 谢谢,这就是我要找的。所以C是科学计算的语言!尽管附录 G 是可选的,但至少它指定了正确的复杂算法。 C++ 和 Fortran 实际上令人失望……
  • Smith 1962 方法是一种复杂除法的策略,可在此处获得:dl.acm.org/citation.cfm?id=368661
猜你喜欢
  • 2013-10-17
  • 1970-01-01
  • 2014-09-21
  • 2017-09-23
  • 1970-01-01
  • 2013-09-07
  • 2021-07-08
  • 2017-01-11
  • 2021-07-05
相关资源
最近更新 更多