给定两个仅在量化或分辨率上有所不同的相似向量,我们可以使用inner_product()算法来计算误差和,定义为:
其中,e是误差和,表示两个向量中一系列点差的平方和。
我们可以使用来自<numeric>头文件的inner_product()算法来计算两个向量之间的误差和。
如何做……
在这个示例中,我们定义了两个向量,每个向量都包含一个正弦波。一个向量是double类型的值,另一个是int类型的值。这给了我们两个在量化上有所不同的向量,因为int类型无法表示分数值。然后,我们使用inner_product()来计算这两个向量之间的误差和:
在main()函数中,我们定义了两个向量和一个方便的索引变量:
int main() {
constexpr size_t vlen{ 100 };
vector<double> ds(vlen);
vector<int> is(vlen);
size_t index{};
// ...
}
ds是double正弦波的向量,is是int正弦波的向量。每个向量都有100个元素来保存一个正弦波。索引变量用于初始化向量对象。
我们使用循环和lambda来在double向量中生成正弦波:
auto sin_gen = [&index]{
return 5.0 * sin(index++ * 2 * pi / 100);
};
for(auto& v : ds) v = sin_gen();
lambda捕获对索引变量的引用,以便它可以递增。
pi常量来自std::numbers库。
现在我们有了double正弦波,我们可以用它来推导int版本:
index = 0;
for(auto& v : is) {
v = static_cast<int>(round(ds.at(index++)));
}
这从ds中获取每个点,四舍五入它,将其转换为int,并在is容器中更新它的位置。
我们使用一个简单的循环来显示我们的正弦波:
for(const auto& v : ds) cout << format("{:-5.2f} ", v);
cout << "\n\n";
for(const auto& v : is) cout << format("{:-3d} ", v);
cout << "\n\n";
我们的输出是两个容器中作为数据点的正弦波:
// 输出正弦波数据点
现在我们使用inner_product()来计算误差和:
double errsum = inner_product(ds.begin(), ds.end(),
is.begin(), 0.0, std::plus<double>(),
[](double a, double b){ return pow(a - b, 2); });
cout << format("error sum: {:.3f}\n\n", errsum);
lambda表达式返回公式中的(ai - bi)2部分。std::plus()算法执行求和操作。
输出:
error sum: 7.304
它是如何工作的……
inner_product()算法计算第一个输入范围内的乘积和。其签名是:
T inner_product(InputIt1 first1, InputIt1 last1,
InputIt2 first2, T init, BinaryOperator1 op1,
BinaryOperator2 op2)
该函数接受两个二元操作符函数对象,op1和op2。第一个op1用于求和,第二个op2用于乘积。我们使用std::plus()作为求和操作符,并使用lambda作为乘积操作符。
init参数可以用作起始值或偏差。我们传递字面值0.0。
返回值是乘积的累积和。
还有更多……
我们可以通过将inner_product()放入循环中来计算累积误差和:
cout << "accumulated error:\n";
for (auto it{ds.begin()}; it != ds.end(); ++it) {
double accumsum = inner_product(ds.begin(), it,
is.begin(), 0.0, std::plus<double>(),
[](double a, double b){ return pow(a - b, 2); });
cout << format("{:-5.2f} ", accumsum);
}
cout << '\n';
输出:
// 输出累积误差
这在一些统计应用中可能是有用的。