【问题标题】:Compute Mutliplication of complex numbers计算复数的乘法
【发布时间】:2016-05-23 16:15:11
【问题描述】:

我最终要做的是将两个复数相乘,如下所示:

z1 = R1 + I1*j

z2 = R2 + I2*j

z3 = z1 * z2 = (R1*R2 - I1*I2) (R1*I2 + R2*I1)*j;

但我拥有的是两个独立的向量,分别用于这两个复数的实部和复数部分。所以是这样的:

v1 = [R1, R2, R3, R4 ... Rn] of z1

v2 = [I1, I2, I3, I4 ... In] of z1

v1 = [R1, R2, R3, R4 ... Rn] of z2

v2 = [I1, I2, I3, I4 ... In] of z2

所以当我现在尝试计算 z3 时,我会这样做:

foo (std::vector<double> real1, std::vector<double> imag1,
     std::vector<double> real2, std::vector<double> imag2)
{
    std::vector<double> realResult;
    std::vector<double> imagResult;

    for (size_t i = 0; i < real1.size(); i++)
    {
         realResult.push_back(real1[i]*real2[i] - imag1[i]*imag2[i]);
         imagResult.push_back(real1[i]*imag2[i] + real2[i]*imag1[i]);
    }

    //And so on
}

现在,这个函数占用了很多时间。肯定有另一种方法可以做到这一点,你能想到我可以使用的东西吗?

【问题讨论】:

  • 预分配结果向量并填充,而不是使用 push_back

标签: c++ arrays vector multiplication complex-numbers


【解决方案1】:

您也许可以使用std::complex。这可能实现了您需要的操作,至少接近于它们可以实现的程度。

编辑(回复评论):

我会这样做:

size_t num_items = real1.size();
std::vector<double> realResult;
realResult.reserve(num_items);
std::vector<double> imagResult;
imagResult.reserve(num_items);
for (size_t i = 0; i < num_items; ++i) {
  // lalala not re-sizeing any vectors yey!
  realResult.push_back(real1[i] * real2[i] - imag1[i] * imag2[i]);
  imagResult.push_back(real1[i] * imag2[i] + real2[i] * imag1[i]);

}

否则,如果您有一个大型输入数组,并且您正在对双精度数进行大量乘法运算,恐怕这可能会很慢。你能做的最好的事情就是让内存中的东西连续以获得奖励缓存点。如果不对代码进行分析,就不可能真正说出最有效的方法。

【讨论】:

  • 如上。我会试一试,但我需要用我的向量填充 std::complex 。你知道一种有效地做到这一点的方法吗?
  • @FreddyKay 我怀疑如果你将结果向量初始化为你期望的大小,或者reserve 那个空间,你会发现它会快很多。我必须进行概要分析才能确定,但​​我怀疑查看该代码可能会耗尽相当多的时间来为结果向量重新分配更多空间。我将编辑我的答案以显示此建议。
  • @FreddyKay 填充复数可以按照首先保留空间并只是循环的相同想法来完成。我建议如果可能的话,您只需将原始数据初始化为 std::compex 的向量,以避免额外的副本。
  • @FreddyKay 另外我第一次编辑完全错了,希望现在我已经制作了一个实际有效的示例!
【解决方案2】:

将参数传入const std::vector&lt;double&gt;&amp;,避免不必要的复制

你也可以考虑并行计算每个乘法,如果N足够大,并行计算的开销是值得的

【讨论】:

  • 显然。谢谢!
【解决方案3】:

使用std::complex 中的std::valarray。它简单且针对算术运算进行了优化

foo(std::valarray<std::complex<double>> & z1, 
    std::valarray<std::complex<double>> & z2) 
{
    auto z3 = z1 * z2;  // applies to each element of two valarrays, or a valarray and a value 

    // . . .
}

编辑:将向量转换为valarray

std::valarray<std::complex<double>> z1(real1.size());
for (size_t i = 0; i < z1.size(); ++i)
    z1[i] = std::complex<double>(real1[i], imag1[i]);

【讨论】:

  • 这看起来不错。我会试一试。虽然我必须用我的向量有效地填充数组。你有什么建议吗?
  • @FreddyKay 在答案中添加。
猜你喜欢
  • 2013-03-13
  • 2013-02-19
  • 2015-08-19
  • 1970-01-01
  • 2010-12-17
  • 1970-01-01
  • 2013-10-22
  • 2023-03-22
  • 1970-01-01
相关资源
最近更新 更多