找出std::vector中所有元素的和的好方法是什么?
假设我有一个向量std::vector<int> vector,其中有几个元素。现在我要求所有元素的和。同样的东西有什么不同的表达方式?
找出std::vector中所有元素的和的好方法是什么?
假设我有一个向量std::vector<int> vector,其中有几个元素。现在我要求所有元素的和。同样的东西有什么不同的表达方式?
当前回答
c++ 0 x只:
vector<int> v; // and fill with data
int sum {}; // or = 0 ... :)
for (int n : v) sum += n;
这类似于其他地方提到的BOOST_FOREACH,与与accumulate或for_each一起使用的有状态函子相比,在更复杂的情况下具有同样的清晰性。
其他回答
我是一个Perl用户,我们有一个游戏是找到各种不同的方法来增加一个变量…这里没有什么不同。在c++中,有多少种方法可以求出一个向量元素的和,答案可能是无穷大……
我的观点是:
使用BOOST_FOREACH,摆脱丑陋的迭代器语法:
sum = 0;
BOOST_FOREACH(int & x, myvector){
sum += x;
}
在索引上迭代(非常容易阅读)。
int i, sum = 0;
for (i=0; i<myvector.size(); i++){
sum += myvector[i];
}
另一个是破坏性的,像访问堆栈一样访问vector:
while (!myvector.empty()){
sum+=myvector.back();
myvector.pop_back();
}
#include<boost/range/numeric.hpp>
int sum = boost::accumulate(vector, 0);
使用inclinclve_scan (c++ 17及以上):
这样做的好处是可以得到一个向量中前“N”个元素的和。下面是代码。在评论中解释。
要使用inclinclve_scan,需要包含“numeric”标头。
//INPUT VECTOR
std::vector<int> data{ 3, 1, 4, 1, 5, 9, 2, 6 };
//OUTPUT VECTOR WITH SUMS
//FIRST ELEMENT - 3
//SECOND ELEMENT - 3 + 1
//THIRD ELEMENT - 3 + 1 + 4
//FOURTH ELEMENT - 3 + 1 + 4 + 1
// ..
// ..
//LAST ELEMENT - 3 + 1 + 4 + 1 + 5 + 9 + 2 + 6
std::vector<int> sums(data.size());
//SUM ALL NUMBERS IN A GIVEN VECTOR.
inclusive_scan(data.begin(), data.end(),
sums.begin());
//SUM OF FIRST 5 ELEMENTS.
std::cout << "Sum of first 5 elements :: " << sums[4] << std::endl;
//SUM OF ALL ELEMENTS
std::cout << "Sum of all elements :: " << sums[data.size() - 1] << std::endl;
还有一种重载,可以指定执行策略。顺序执行或并行执行。需要包括“执行”头。
//SUM ALL NUMBERS IN A GIVEN VECTOR.
inclusive_scan(std::execution::par,data.begin(), data.end(),
sums.begin());
使用reduce:
我在答案中没有注意到的另一个选项是使用c++17中引入的std::reduce。
但是你可能会注意到很多编译器不支持它(GCC 10以上可能就不错了)。但最终支持会来的。
使用std::reduce,优势在于使用执行策略。指定执行策略可选。当指定执行策略为std::execution::par时,算法可能会使用硬件并行处理能力。当使用大尺寸向量时,增益可能会更明显。
例子:
//SAMPLE
std::vector<int> vec = {2,4,6,8,10,12,14,16,18};
//WITHOUT EXECUTION POLICY
int sum = std::reduce(vec.begin(),vec.end());
//TAKING THE ADVANTAGE OF EXECUTION POLICIES
int sum2 = std::reduce(std::execution::par,vec.begin(),vec.end());
std::cout << "Without execution policy " << sum << std::endl;
std::cout << "With execution policy " << sum2 << std::endl;
std::reduce需要<numeric>报头。 和'<execution>'用于执行策略。
既然可以倒着做求和,为什么还要往前做呢?考虑到:
std::vector<int> v; // vector to be summed
int sum_of_elements(0); // result of the summation
我们可以使用下标,向后计数:
for (int i(v.size()); i > 0; --i)
sum_of_elements += v[i-1];
我们可以使用范围检查的“下标”,向后计数(以防万一):
for (int i(v.size()); i > 0; --i)
sum_of_elements += v.at(i-1);
我们可以在for循环中使用反向迭代器:
for(std::vector<int>::const_reverse_iterator i(v.rbegin()); i != v.rend(); ++i)
sum_of_elements += *i;
我们可以在for循环中使用前向迭代器,向后迭代(哦,很棘手!):
for(std::vector<int>::const_iterator i(v.end()); i != v.begin(); --i)
sum_of_elements += *(i - 1);
我们可以对反向迭代器使用accumulate:
sum_of_elems = std::accumulate(v.rbegin(), v.rend(), 0);
我们可以使用反向迭代器将for_each与lambda表达式一起使用:
std::for_each(v.rbegin(), v.rend(), [&](int n) { sum_of_elements += n; });
所以,正如你所看到的,向后求和的方法和正向求和的方法一样多,其中一些更令人兴奋,并且提供了更大的机会出现差1的错误。
也可以像这样使用std::valarray<T>
#include<iostream>
#include<vector>
#include<valarray>
int main()
{
std::vector<int> seq{ 1,2,3,4,5,6,7,8,9,10 };
std::valarray<int> seq_add{ seq.data(), seq.size() };
std::cout << "sum = " << seq_add.sum() << "\n";
return 0;
}
有些人可能不觉得这种方法有效,因为valarray的大小需要和vector的大小一样大,并且初始化valarray也需要时间。
在这种情况下,不要使用它,把它作为另一种对序列求和的方式。