【问题标题】:Multiplying a valarray of complex numbers by a scalar将复数的 valarray 乘以标量
【发布时间】:2016-09-15 16:55:03
【问题描述】:

valarray<double> 可以乘以一个标量。但是,当我想乘以 valarray<complex<double>> 的标量时出现错误。我想知道是否有办法以一种漂亮的方式做到这一点。这是问题的重现:

valarray<complex<double>> v1{ { complex<double>{1,0}, complex<double>{2,0}, complex<double>{3,0} } };
valarray<complex<double>> v2 = v1 * 2.0; // error

生成Error C2784: 'std::complex&lt;_Other&gt; std::operator *(const std::complex&lt;_Other&gt; &amp;,const std::complex&lt;_Other&gt; &amp;)': could not deduce template argument for 'const std::complex&lt;_Other&gt; &amp;' from 'std::vector&lt;std::complex&lt;double&gt;,std::allocator&lt;_Ty&gt;&gt;'

所以我尝试构建自己的功能,看看是否可以完成并且以下工作:

valarray<complex<double>> VAMult(const valarray<complex<double>> &v, double scalar)
{
    valarray<complex<double>> out(v.size());
    for (size_t i = 0; i < v.size(); i++)
    {
        out[i] = v[i] * scalar;
    }
    return out;
}

// makes the following code work:
valarray<complex<double>> v2 = VAMult(v1, 2.0);

但是这个实现会产生非常丑陋的代码,所以我查看了 valarray.h 并找到了 * 重载定义:

operator*(const _Ty& _Left,
        const valarray<_Ty>& _Right)
{   // return scalar * valarray
    _VALOP(_Ty, _Right.size(), _Left * _Right[_Idx]);
}

#define _VALOP(TYPE, LENGTH, RHS)   /* assign RHS(_Idx) to new valarray */ \
valarray<TYPE> _Ans(LENGTH); \
for (size_t _Idx = 0; _Idx < _Ans.size(); ++_Idx) \
    _Ans[_Idx] = RHS; \
return (_Ans)

我的模板知识非常有限,但是可以扩展这个类吗?这是我的尝试:

valarray<complex<double>> valarray<complex<double>>::operator*(const double &scalar)
{
    return valarray<complex<double>>{};
}

导致Error C2039 '*': is not a member of 'std::valarray&lt;std::complex&lt;double&gt;&gt;'

有没有办法让我的第一行代码v1 * 2.0 工作或一些接近妥协?

【问题讨论】:

    标签: c++ c++11 stl complex-numbers valarray


    【解决方案1】:

    有没有办法让我的第一行代码 v1 * 2.0 工作或 某种妥协?

    是:将v1 与复数标量相乘。

    以下代码编译

    #include <complex>
    #include <valarray>
    
    int main()
     {
       std::valarray<std::complex<double>> v1{ { {1,0}, {2,0}, {3,0} } };
       std::valarray<std::complex<double>> v2 = v1 * std::complex<double>{2.0};
     }
    

    问题在于valarray 是一个模板类,它带有一个仅在模板类型上定义的operator*()(和类似的运算符)。

    所以std::valarray&lt;double&gt; 可以与double 标量相乘,std::valarray&lt;std::complex&lt;double&gt;&gt; 可以与std::complex&lt;double&gt; 标量相乘,但std::valarray&lt;std::complex&lt;double&gt;&gt; 不能与double 标量相乘。

    【讨论】:

    • 我可以发誓我试过这个,但第二个和第三个值是随机的。考虑到我的范围有限,这是一个可以接受的折衷方案。
    【解决方案2】:

    在这种情况下,专门化 operator* 是非法的,不会得到你想要的。

    可以重载,但将重载添加到namespace std 是非法的。 (这可能会在 中更改)

    我们可以做到:

    valarray<complex<double>> v1{ { complex<double>{1,0}, complex<double>{2,0}, complex<double>{3,0} } };
    valarray<complex<double>> v2 = v1 * complex<double>{2.0};
    

    但我想你知道这一点。

    您可以使用named operators 并获取:

    valarray<complex<double>> v2 = v1 *times* 2.0;
    

    合法工作。

    您也可以编写自己的文字到复数转换器:

    std::complex<double> operator"" _cplx( long double t ) {
      return {(double)std::move(t)};
    }
    

    Live example.

    但是说真的,投到complex&lt;double&gt;

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-19
      • 1970-01-01
      • 1970-01-01
      • 2019-04-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多