> 文章列表 > std::inner_product与std::accumulate初始值设置踩坑

std::inner_product与std::accumulate初始值设置踩坑

std::inner_product与std::accumulate初始值设置踩坑

std::inner_product函数可以用于计算两个序列的内积。在这个函数中,我们需要传递四个参数:两个源序列的起始迭代器、一个初始值和一个二元函数对象。

std::inner_product函数将对两个源序列中的每个元素进行乘法运算,并将结果累加到初始值中,最终返回累加结果。

以下是一个示例代码,演示了如何使用std::inner_product函数计算两个序列的内积:

#include <iostream>
#include <vector>
#include <numeric>double calc_confi_interval(double rtt_interval_ratio) {return 1.96 * rtt_interval_ratio / std::sqrt(2);
}int main() {std::vector<double> rtt_interval_ratios = {0.5, 0.6, 0.7, 0.8, 0.9};std::vector<double> rtt_interval_weights = {0.1, 0.2, 0.3, 0.4, 0.5};std::vector<double> rtt_interval_confidences(rtt_interval_ratios.size());int N_intervals = 3;std::transform(rtt_interval_ratios.begin(), rtt_interval_ratios.begin() + N_intervals,rtt_interval_confidences.begin(), calc_confi_interval);double res = std::inner_product(rtt_interval_confidences.begin(), rtt_interval_confidences.begin() + N_intervals,rtt_interval_weights.begin(), 0.0);std::cout << res << std::endl;return 0;
}

在这个示例代码中,我们定义了一个函数calc_confi_interval,用于计算置信区间。我们还定义了两个序列rtt_interval_ratiosrtt_interval_weights,分别表示RTT间隔比率和权重。我们使用std::transform函数将rtt_interval_ratios序列中的前N_intervals个元素转换为置信区间,并将结果存储到rtt_interval_confidences序列中。最后,我们使用std::inner_product函数计算rtt_interval_confidences序列和rtt_interval_weights序列的内积,并将结果存储到res变量中。

通过使用std::inner_product函数,我们可以方便地计算两个序列的内积。在二元函数对象中,我们可以根据需要定义不同的运算规则,以便满足不同的计算需求。

std::inner_product函数的初始值对于结果类型有影响,初始值的类型必须与源序列和二元函数对象的返回类型相同,否则计算可能会有精度丢失。

以下是一个示例代码,演示了初始值类型与结果类型不匹配时会导致结果出错:

int main() {std::vector<int> v1 = {1, 2, 3};std::vector<double> v2 = {1.1, 2.2, 3.3};auto res = std::inner_product(v1.begin(), v1.end(), v2.begin(), 0);std::cout << res << std::endl;return 0;
}

std::inner_product与std::accumulate初始值设置踩坑
初始值改为0.0

int main() {std::vector<int> v1 = {1, 2, 3};std::vector<double> v2 = {1.1, 2.2, 3.3};auto res = std::inner_product(v1.begin(), v1.end(), v2.begin(), 0.0);std::cout << res << std::endl;return 0;
}

std::inner_product与std::accumulate初始值设置踩坑
计算结果也正确了。
与之类似的例如std::accumulate

int main() {std::vector<double> v = {1.1, 2.2, 3.3, 4.4, 5.5};auto sum = std::accumulate(v.begin(), v.end(), 0);std::cout << "sum = " << sum << std::endl;return 0;
}

std::inner_product与std::accumulate初始值设置踩坑
计算结果为15,明显丢失精度了。
初始值改为0.0

int main() {std::vector<double> v = {1.1, 2.2, 3.3, 4.4, 5.5};auto sum = std::accumulate(v.begin(), v.end(), 0.0);std::cout << "sum = " << sum << std::endl;return 0;
}

std::inner_product与std::accumulate初始值设置踩坑
结果为16.5,正确。
其他也有一些函数有初始值的坑,这里简单提及一下即可:
std::transform_reduce函数:在计算序列的变换和缩减时,初始值的类型应该与变换和缩减函数的返回类型相同,否则可能会导致类型转换错误或精度损失。

std::partial_sum函数:在计算序列的部分和时,初始值的类型应该与序列的元素类型相同,否则可能会导致类型转换错误或精度损失。

std::reduce函数:在计算序列的缩减时,初始值的类型应该与缩减函数的返回类型相同,否则可能会导致类型转换错误或精度损失。