C++ STL 中是否有等效的 Polyval(Matlab 函数)?
Is there a Polyval (Matlab's function) equivalent in C++ STL?
我需要在多个点上计算某个程度 (<10) 的多项式(1 维)。
例如,当计算多项式 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;
}
}
不确定在性能方面是否有更好的方法。
正如评论中所建议的,我现在使用 Horner 的方法,基于多项式评估的 Boost 实现,主要区别是:
多项式阶数-在这个解决方案中,与Matlab相同,最高多项式次数在前。
例如:p(x) = 4x^3 + 2*x^2 -2*x + 5
表示为这样的 vector
{ 4, 2, -2, 5}
计算多个值。
#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()
与 Horner 的方法)
指标
Polynomial : p(x) = 4*x^5 + 2*x^4 -2*x^3 + 5*x + 15
Runs : 10,000
Points to evaluate : {0, 2, -4, 8, 15, 1.25, 512 ,-5.3 ,12.215, 153, 23, -11}
Build type : RELEASE
Duration times : pow
- 46,576[microseconds] vs. Horner -6,500[microseconds]
Duration difference : ~ 7 times faster (in favor of Horner's method)
像这样测量的持续时间,对于两种实现:
#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;
我需要在多个点上计算某个程度 (<10) 的多项式(1 维)。
例如,当计算多项式 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;
}
}
不确定在性能方面是否有更好的方法。
正如评论中所建议的,我现在使用 Horner 的方法,基于多项式评估的 Boost 实现,主要区别是:
多项式阶数-在这个解决方案中,与Matlab相同,最高多项式次数在前。 例如:
p(x) = 4x^3 + 2*x^2 -2*x + 5
表示为这样的vector
{ 4, 2, -2, 5}
计算多个值。
#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()
与 Horner 的方法)
指标
Polynomial :
p(x) = 4*x^5 + 2*x^4 -2*x^3 + 5*x + 15
Runs : 10,000
Points to evaluate :
{0, 2, -4, 8, 15, 1.25, 512 ,-5.3 ,12.215, 153, 23, -11}
Build type : RELEASE
Duration times :
pow
- 46,576[microseconds] vs. Horner -6,500[microseconds]Duration difference : ~ 7 times faster (in favor of Horner's method)
像这样测量的持续时间,对于两种实现:
#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;