在 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<double>(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>> 的参数
如何使用 SSE 加载 std::complex 数组的实部?
从 std::complex<MyType> 到 std::complex<double> 的类型转换