【问题标题】:C++ complex number multiplicationC++ 复数乘法
【发布时间】:2014-07-19 15:51:51
【问题描述】:

如果我有 (1+i)^2,答案应该是 2i

如果我这样做了

std::complex<double> i = sqrt(1), one = 1;
cout << pow(one+i,2) << endl;

它输出(4,0)

【问题讨论】:

  • 1 的平方根不是 i。
  • 您的输出全部来自1+1=2
  • @andi 按照惯例,-x 平方根(对于x&gt;0)指的是i 乘以x 的正平方根
  • @andi:你是怎么从sqrt(-1)*sqrt(-1)sqrt(-1*-1) 的?
  • 我现在感觉很愚蠢,这是多么可笑的错误!

标签: c++ complex-numbers


【解决方案1】:

您正在将i 初始化为sqrt(1),而您可能考虑过sqrt(-1)。 因此,它将被评估为 double 表达式(在 -1 转换为最接近匹配 sqrt 的两倍后,请参阅 Mike 的完整序列评论),根据 cplusplus.com,它会为否定参数生成域错误。

相反,您可以将i 初始化为:

std::complex<double> i(0,1);

或者,您可以使用复数作为sqrt 的参数,如this answer 中所述,或者如Potatoswatter 在 cmets 中指出的那样,您可以将1.i 与 C++14 一起使用(如果您有一个编译器和标准库,支持user-defined literals for standard library types, part 2)。

【讨论】:

  • 如果这个答案能解释为什么 sqrt(-1) 是错误的语法,我会更高兴,因为这似乎是 OP 混乱的关键部分。
  • std::complex&lt;double&gt; i = sqrt(-1) 按此顺序有效地执行以下操作:1) 创建一个整数值 "-1" 2) 尝试将其传递给 sqrt(),它有 doublecomplex&lt;double&gt; 版本. double 是更接近的类型转换,因此它将-1 隐式转换为-1.0 并调用double sqrt(double)。 3) 该函数不能处理负数,所以它将errno 设置为EDOM 并返回一个未定义的double。 4) double 被传递给std::complex&lt;T&gt;(T) 构造函数,其中Tdouble。结果:具有未定义实部和0.0 虚部的复数。
  • @Mike 很好的澄清,不知道怎么说更好。一旦我知道答案,我就会在心里跳过步骤。
  • C++14 添加数字文字语法1.i3.5if4.0000001il
【解决方案2】:

C++ 中的math.h 标头提供了sqrt 的以下重载:

auto sqrt( float arg ) -> float;
auto sqrt( double arg ) -> double;
auto sqrt( long double arg ) -> long double;
auto sqrt( Integral arg ) -> double;    // C++11 and later

其中Integral 表示任何整数类型(这是一组重载或函数模板)。

&lt;complex&gt; 标头另外定义了这个重载:

template< class T >
auto sqrt( complex<T> const& x ) -> complex<T>;

valarray 也有一个重载,但在这里不相关。

当您使用-1 作为实际参数时,例如

sqrt( -1 )

参数类型的直接匹配,带有Integral 参数的重载是最合适的,并且该重载返回double

无法将数学 i 表示为 double 值。所以你得到的值是一个实现定义的值(如果你的C++实现的double类型支持NaN,不是数字,它可以是一个NaN); “整数是否 根据 C99 §7.12.1/2,表达式 errno 获取值 EDOM 是实现定义的”。为避免这种情况,您可以确保将 -1 转换为 complex&lt;double&gt; 类型的参数,例如:

sqrt( complex<double>( -1 ) )

使用我尝试过的编译器,这会产生与编写相同的结果

complex<double>( 0, 1 )

代表数学的i,负1的平方根。

【讨论】:

  • The C++ reference for sqrt I found 在输入为负数时没有提及返回值,所以我认为这是未定义的行为。你可能会也可能不会得到 NaN。
  • en.cppreference.com 通常是更好的参考,但在this case 中它包含纯虚假信息:“如果发生域错误,则返回实现定义的值(支持的情况下为 NaN)”。相反,C99 标准说“如果参数小于零,则会发生域错误。”,而 C++11 说“如果函数的参数具有无效值(例如函数域之外的值或指针对其预期用途无效),行为未定义”。谢谢!,已更正。
  • @Cheersandhth.-Alf 我不同意:您引用的 [res.on.arguments]/1 说“除非另有明确说明”,实际上对于 cmath 函数另有明确说明.
  • @Cubbi:是的,并入 C++11 的 C99 标准另有说明。与 cppreference.com 几乎但不完全相同:C++99 §7.12.1/2 “在域错误中,函数返回实现定义的值;整数表达式 errno 是否获取值 EDOM 是实现定义”。不同之处在于 cppreference.com 要求在支持的地方返回 NaN,而不是标准 AFAICS 实际要求的。所以我在迈克评论之前的原始措辞更正确。定影。谢谢!
  • C99 要求在支持 Ieee 数学的情况下返回 NaN(授予通用“如果支持”来自 posix)。我想我可能会更加迂腐,在非 ieee 部分说“典型地”之类的话
猜你喜欢
  • 2014-05-05
  • 2015-06-09
  • 2021-12-08
  • 2013-07-05
  • 2012-06-06
  • 2012-09-18
  • 2012-01-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多