accumulate函数
2021-0506修正
参考资料:
https://en.cppreference.com/w/cpp/algorithm/accumulate
函数原型(目前有两个版本):
template< class InputIt, class T > constexpr T accumulate( InputIt first, InputIt last, T init ); template< class InputIt, class T, class BinaryOperation > constexpr T accumulate( InputIt first, InputIt last, T init, BinaryOperation op );
从模板函数原型即可见,返回值类型是和参数三的类型一致的。
复制下参考资料里的两个版本实现示例代码:
First version |
---|
template<class InputIt, class T>
constexpr // since C++20
T accumulate(InputIt first, InputIt last, T init)
{
for (; first != last; ++first) {
init = std::move(init) + *first; // std::move since C++20
}
return init;
}
|
Second version |
template<class InputIt, class T, class BinaryOperation>
constexpr // since C++20
T accumulate(InputIt first, InputIt last, T init,
BinaryOperation op)
{
for (; first != last; ++first) {
init = op(std::move(init), *first); // std::move since C++20
}
return init;
}
|
注意的是,如果第三个参数传的只是0,即使序列是double型的数据,返回的也是整型的,
而且,每一步计算的时候都会涉及类型的隐式转换(小数去尾)。并不是说double序列算个总和再去尾,而是每个值都去尾再想加。
写个试验代码:
void funcRun_accumulate() { std::vector<double> vecTest{ 3,3,2.9,8.9 }; std::cout<< std::accumulate(vecTest.begin(), vecTest.end(), 0.0)<<std::endl;// 17.8 std::cout << std::accumulate(vecTest.begin(), vecTest.end(), 0) << std::endl;// 16 }
再一个极端点的试验代码,序列值都是不大于1的小数:
void funcRun_accumulate2() { std::vector<double> vecTest{ 0.3,0.3,0.9,0.9 }; std::cout << std::accumulate(vecTest.begin(), vecTest.end(), 0.0) << std::endl;// 2.4 std::cout << std::accumulate(vecTest.begin(), vecTest.end(), 0) << std::endl;// 0 }
ps.
另外,这个函数依赖的头文件是 #include <numeric>,而不是<algorithm>
而当我写如下的测试代码的时候,vs2017社区版能正常计算结果,但总给我警告:xxxx2017communityvc oolsmsvc14.16.27023include
umeric(26): warning C4244: “=”: 从“double”转换到“_Ty”,可能丢失数据
感觉不应该有警告才对呢:
#include <string> namespace AccumulateOpNS { std::string LinkStr(const std::string &init, double dv) { return ""; //return init + "_" + std::to_string(dv); } } void funcRun_accumulate3() { std::vector<double> vecTest{ 0.3,0.3,0.9,0.9 }; std::string begStr("beg"); std::cout << std::accumulate(vecTest.begin(), vecTest.end(), begStr, AccumulateOpNS::LinkStr) << std::endl; // beg_0.300000_0.300000_0.900000_0.900000 }