【问题标题】:Is there a Polyval (Matlab's function) equivalent in C++ STL?C++ STL 中是否有等价的 Polyval(Matlab 的函数)?
【发布时间】:2020-06-09 07:23:30
【问题描述】:

我需要在多个点上评估某个程度 (p(x) = 4x^3 + 2*x^2 -2*x + 5 时,x = 0, x= 2 结果应该是:[5, 41]。 找不到与 Matlab 的 Polyval 等效的函数。

结果的准确性对我来说并不重要(可以四舍五入为整数),但计算时间是。

我的直截了当的解决方案:

#include<iostream>
#include<vector>
#include<math.h>

std::vector<double> Polyval(std::vector<double> coeffs, std::vector<double> values)
{
  std::vector<double> results;
    for (auto const &val:values)
        {
          double result = 0;
          for (int i = 0, deg = coeffs.size() - 1; deg >= 0; deg--, i++)
            {
                result += coeffs[i] * std::pow(val, deg);
            }
          results.push_back (result);
        }
        return results;
}

int main()
{
  std::vector<double> coeffs = { 4, 2, -2, 5};
  std::vector<double> valuesToEvaluate = { 0, 2 , -4};
  std::vector<double> results = Polyval (coeffs, valuesToEvaluate);

  for (auto const &res:results)
    {
      std::cout << res << std::endl;
    }
}

不确定在性能方面是否有更好的方法。

【问题讨论】:

  • 你可以放弃std::pow作为初学者,并在你去的时候积累x的力量。请参阅下一条注释了解此方法的名称:
  • 使用Horner's method
  • 除非您的应用程序的运行时间上限为微秒级,否则我认为优化简单的 for 循环不会对您的代码产生任何影响。 “过早的优化是万恶之源”
  • 从0度开始,积累价值的力量。根本不需要使用std::pow()

标签: c++ matlab polynomials polynomial-math


【解决方案1】:

正如 cmets 中所建议的,我现在使用霍纳的方法,基于多项式评估的 Boost 实现,主要区别是:

  1. 多项式阶 - 在此解决方案中,与 Matlab 相同,最高多项式次数排在第一位。 例如:p(x) = 4x^3 + 2*x^2 -2*x + 5 表示为 vector 就像这样 { 4, 2, -2, 5}

  2. 计算多个值。

#include<assert.h>
#include<vector>

std::vector<double> Polyval(std::vector<double> coeffs, std::vector<double> values)
{
  assert(coeffs.size() > 0);
  std::vector<double> results;
  for (auto const &val:values)
  {
      double result = coeffs[0];
      for (int i = 1; i < coeffs.size(); i++)
        {
            result *= val;
            result += coeffs[i];
        }
        results.push_back (result);
    }
    return results;
}

编辑: 添加两种方法的性能指标(使用pow() vs. Horner 方法

指标

多项式:p(x) = 4*x^5 + 2*x^4 -2*x^3 + 5*x + 15

运行:10,000

评估点:{0, 2, -4, 8, 15, 1.25, 512 ,-5.3 ,12.215, 153, 23, -11}

构建类型:发布

持续时间:pow - 46,576[微秒] vs. Horner -6,500[微秒]

持续时间差异:约快 7 倍(支持霍纳的方法)

这样测量的持续时间,适用于两种实现:

#include<iostream>
#include<assert.h>
#include<vector>
#include<chrono>

    int iter = 10000;
    std::vector<double> coeffs = { 4, 2, -2, 5, 0, 15};
    std::vector<double> valuesToEvaluate = {0, 2, -4, 8, 15, 1.25, 512 ,-5.3 
    ,12.215, 153, 23, -11};
    auto start = std::chrono::high_resolution_clock::now();

    do{
    std::vector<double> results = Polyval(coeffs, valuesToEvaluate);
    }
    while(iter-->0);

    auto end = std::chrono::high_resolution_clock::now();
    long duration = std::chrono::duration_cast<std::chrono::microseconds>(end - 
    start).count();

    std::cout << duration << std::endl;

【讨论】:

  • @AnderBiguri - 我添加了性能指标,如果你也测试过,请分享。
  • 我的意思是实际结果(以毫秒为单位),但我猜这没关系。
  • @AnderBiguri - 已编辑,平均破坏上述计算 10 次。
猜你喜欢
  • 1970-01-01
  • 2019-12-15
  • 1970-01-01
  • 1970-01-01
  • 2018-03-26
  • 1970-01-01
  • 2012-10-20
  • 2012-10-09
相关资源
最近更新 更多