在 C++ 中使用 std::complex<T> 创建复无穷大

Posted

技术标签:

【中文标题】在 C++ 中使用 std::complex<T> 创建复无穷大【英文标题】:Creating complex infinity with std::complex<T> in C++ 【发布时间】:2012-05-22 03:36:06 【问题描述】:

我正在尝试创建一个等于 Inf+Inf*j 的复无穷大,其中 j 是复变量。当我这样做时:

#include <complex>
#include <limits>
using std;

...

complex<double> attempt1 =
   complex<double>( numeric_limits<double>::infinity(),
                    numeric_limits<double>::infinity() );

返回复数 (NaN + Inf*j)。

但是

complex<double> attempt2 =
   complex<double>( numeric_limits<double>::infinity() );

返回复数 (Inf + 0*j)。

还有:

complex<double> attempt_at_imag_inf =
   complex<double>(any_value_here, numeric_limits<double>::infinity());

返回复数 (NaN + Inf*j)。

有人知道这里发生了什么吗?每当我尝试将虚部设为无穷大时,就会在实部上写入 NaN。

以上内容当然只适用于支持 NaN 和 Infinity 的类型。我正在使用 g++ v4.6.1。我查看了 numeric_limits 标头,没有迹象表明上述情况应该发生。

为了将上述内容置于上下文中,我实际上是在对复杂的 numeric_limits 进行部分专业化时执行上述操作。非常感谢您考虑这个问题。

对原帖的修订

我提供了一个完整但简短的程序来说明问题。我还提供了一些关于如何编译程序以生成结果的更多限定信息。

#include <iostream>
#include <complex>
#include <limits>

using namespace std;

int main(int argc, char* argv[])


   complex<double> my_complex_inf =
      complex<double>(numeric_limits<double>::infinity(),
                      numeric_limits<double>::infinity());

   cout << "my_complex_inf = " << my_complex_inf << endl;

   complex<double> attempt2 =
      complex<double>( numeric_limits<double>::infinity() );

   cout << "attempt2 = " << attempt2 << endl;

   double any_value_here = 0;

   complex<double> attempt_at_imag_inf =
      complex<double>(0, numeric_limits<double>::infinity());

   cout << "attempt_at_imag_inf = " << attempt_at_imag_inf << endl;

   return 0;


在 Ubuntu 上使用 -std=c++0x 在 g++ 版本 4.6.1 中编译上述内容会得到以下结果:

my_complex_inf = (nan,inf)
attempt2 = (inf,0)
attempt_at_imag_inf = (nan,inf)

如果没有 -std=c++0x 选项,结果是:

my_complex_inf = (inf,inf)
attempt2 = (inf,0)
attempt_at_imag_inf = (0,inf)

所以问题真的是为什么 GNU g++ V4.6.1 在指定 C++0x 时给出它的答案?

第 2 版原帖

我刚刚在 Octave(类似 MATLAB 的数值包)中尝试了以下内容:

a=inf + j*inf

答案是:

a = NaN + Infi

这正是我在 C++11 代码 (C++0x) 中看到的。我不知道 Octave 是用什么编译的(我相信它是 C++ 和 FORTRAN 的组合),但如果该包返回我得到的结果,那么我认为这是众所周知的行为。

但是,我查看了 C++11 草案标准,找不到任何提及此行为的内容。

第 3 版原帖

添加以下行

my_complex_inf.real(my_complex_inf.imag());

在为 C++11 编译时,在构建 my_complex_inf 之后返回“正确”答案(inf,inf)。不幸的是,现在这是一个两步过程,我无法在 constexpr 函数中创建这种复杂的无穷大。

【问题讨论】:

它可以正常工作on g++4.3.4、g++4.5.1、4.6.3 和 4.7.0。请提供一个简短、完整的示例程序。见sscce.org。 你确定你想要复平面的 4 个可能的无穷大吗?我认为您只需要一个(例如在黎曼球中)。 好吧,你可以试试1 / std::complex&lt;double&gt;(0),因为如果你想代表黎曼球体,你唯一想要的就是1 / infty == 0 它在clang++ 3.5 中按预期工作。我可以构造所有这些数字,(inf,1) (1,inf) (inf,inf) 【参考方案1】:

转换为复数的标量 Inf 是 inf+0 j。上面是对的。复平面中的标量 Inf 偏移意味着 a 旋转并且不可计算,因此 Nan 是正确的。又是什么问题?

“有龙。”

【讨论】:

令 a = 1 即 1+0*j。 pi/4 的旋转为 1*exp(jpi/4),即 sqrt(2)+jsqrt(2)。如果 a 是 inf,则 b=infexp(jpi/4)。由于这仅涉及实数和复数部分的 inf 相乘,因此结果也应该是 inf (对于实数和复数部分)。所以我认为 nan 不应该出现在旋转的计算中,如果这是它是如何实现的。【参考方案2】:

您遇到了 C++11(和 C11)指定复数的方式并感到困惑。

基本上,在规范规定的模型中,只有一个无穷大(由 (inf,0) 表示),并试图将“无穷大”放入 Nan 的复数结果的虚部,因为它使在那个模型中没有意义。

【讨论】:

【参考方案3】:

在主线 (gcc-4.8) 中,我使用 -std=c++0x 得到预期的(无 -std)答案:

my_complex_inf = (inf,inf)
attempt2 = (inf,0)
attempt_at_imag_inf = (0,inf)

gcc-4.6.3 with -std-c++11 给出了意想不到的答案:

my_complex_inf = (-nan,inf)
attempt2 = (inf,0)
attempt_at_imag_inf = (-nan,inf)

我认为构造函数应该只是根据相应的参数设置实数和虚数类型。应该没有nan

【讨论】:

以上是关于在 C++ 中使用 std::complex<T> 创建复无穷大的主要内容,如果未能解决你的问题,请参考以下文章

在 boost::asio::buffer 中使用类似 std::vector<std::complex<double>> 的参数

std::complex类conj

如何使用 SSE 加载 std::complex 数组的实部?

从 std::complex<MyType> 到 std::complex<double> 的类型转换

使用 AVX2 高效计算 std::complex<float> 向量的绝对值

在 C++ 中初始化复数数组