查找std::vector
中所有元素总和的好方式是什么?
假设我有一个向量std::vector<int> vector
,其中包含一些元素。现在我想找到所有元素的总和。有什么不同的方法?
答案 0 :(得分:371)
实际上有很多方法。
int sum_of_elems = 0;
Classic for循环:
for(std::vector<int>::iterator it = vector.begin(); it != vector.end(); ++it)
sum_of_elems += *it;
使用标准算法:
#include <numeric>
sum_of_elems = std::accumulate(vector.begin(), vector.end(), 0);
标志
小心累积。最后一个参数的类型不仅用于初始值,还用于结果的类型。如果你在那里放一个int,即使向量有浮点数,它也会累积整数。如果您要汇总浮点数,请将0
更改为0.0
或0.0f
(感谢nneonneo)。
使用std::for_each
:
std::for_each(vector.begin(), vector.end(), [&] (int n) {
sum_of_elems += n;
});
使用基于范围的for循环(感谢Roger Pate):
for (auto& n : vector)
sum_of_elems += n;
答案 1 :(得分:30)
Prasoon已经提供了许多不同的(和好的)方法来做到这一点,这些都不需要在这里重复。我想建议一种替代的速度方法。
如果您打算这么做,您可能需要考虑对您的向量进行“子类化”,以便单独维护一个元素的总和(而不是实际上子类别由于缺少虚拟析构函数而导致iffy的向量 - 我说的更多的是一个包含求和和其中的向量的类,has-a
而不是is-a
,并且提供了类似向量的向量方法)。
对于空向量,总和设置为零。在向量的每次插入时,将要插入的元素添加到总和中。在每次删除时,减去它。基本上,可以拦截可以改变基础向量的任何以确保总和保持一致。
这样,你有一个非常有效的O(1)方法来“计算”任何时间点的总和(只返回当前计算的总和)。在调整总数时,插入和删除时间会稍长,您应该考虑这种性能影响。
需要比矢量更改所需的和更多的向量是可能受益于此方案的向量,因为计算总和的成本在所有访问中摊销。显然,如果你每小时只需要总和,并且矢量每秒变化三千次,那就不合适了。
这样的东西就足够了:
class UberVector:
private Vector<int> vec;
private int sum;
public UberVector():
vec = new Vector<int>();
sum = 0;
public getSum():
return sum;
public add (int val):
rc = vec.add (val)
if rc == OK:
sum = sum + val
return rc
public delindex (int idx):
val = 0
if idx >= 0 and idx < vec.size:
val = vec[idx]
rc = vec.delindex (idx)
if rc == OK:
sum = sum - val
return rc
显然,这是伪代码,您可能希望获得更多功能,但它显示了基本概念。
答案 2 :(得分:22)
为什么在你可以向后的情况下执行向前求和?给出:
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; });
所以,正如你所看到的,有很多方法可以向后求和向量,因为它可以对向量求和进行求和,其中一些更令人兴奋,并为逐个错误提供了更大的机会
答案 3 :(得分:14)
#include<boost/range/numeric.hpp>
int sum = boost::accumulate(vector, 0);
答案 4 :(得分:12)
最简单的方法是使用 const emitMock = jest.spyOn(TestStore, 'emit');
let ACTION = 'Test-Action';
let payload = {
action: ACTION,
emitOn: [{
store: TestStore, // The store to emit on
componentIds: ['Test-Id']
}]
};
AppActions.finish(payload);
expect(emitMock).toHaveBeenCalledTimes(1);
中的std:accumuate
:
vector<int> A
答案 5 :(得分:5)
我是Perl用户,我们的游戏是找到增加变量的每种不同方式......这在这里并没有什么不同。在C ++中找到向量元素总和的方法的答案可能是an infinity
...
我的2美分:
使用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];
}
另一个是破坏性的,像堆栈一样访问矢量:
while (!myvector.empty()){
sum+=myvector.back();
myvector.pop_back();
}
答案 6 :(得分:5)
仅限C ++ 0x:
vector<int> v; // and fill with data
int sum {}; // or = 0 ... :)
for (int n : v) sum += n;
这类似于其他地方提到的BOOST_FOREACH,与使用accumulate或for_each的有状态仿函数相比,在更复杂的情况下具有相同的清晰度。
答案 7 :(得分:2)
也可以像这样使用std :: valarray
tableView.beginUpdates()
// set your image in cell here
tableView.endUpdates()
有些人可能找不到这种方式有效,因为valarray的大小需要与向量的大小一样大,初始化valarray也需要时间。
在这种情况下,不要使用它,并将其作为总结序列的另一种方式。
谢谢
答案 8 :(得分:1)
我在答案中没有注意到的另一个选项是使用 std::reduce
,它是在 c++17 中引入的。
但是您可能会注意到许多编译器不支持它(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;
您需要 <numeric>
的 std::reduce
标头。
和 '<execution>'
用于执行策略。
答案 9 :(得分:0)
我找到了找到一个元素的所有元素之和的最简单方法 向量
#include <iostream>
#include<vector>
using namespace std;
int main()
{
vector<int>v(10,1);
int sum=0;
for(int i=0;i<v.size();i++)
{
sum+=v[i];
}
cout<<sum<<endl;
}
在此程序中,我有一个大小为10的向量,并由1初始化。我已经通过数组中的简单循环计算了总和。
答案 10 :(得分:0)
#include<iostream>
#include<vector>
#include<numeric>
using namespace std;
int main() {
vector<int> v = {2,7,6,10};
cout<<"Sum of all the elements are:"<<endl;
cout<<accumulate(v.begin(),v.end(),0);
}
答案 11 :(得分:0)
似乎没有人解决对可以包含 NaN 值的向量元素求和的情况,例如numerical_limits<double>::quite_NaN()
我通常遍历元素并直截了当地检查。
vector<double> x;
//...
size_t n = x.size();
double sum = 0;
for (size_t i = 0; i < n; i++){
sum += (x[i] == x[i] ? x[i] : 0);
}
它一点也不花哨,即没有迭代器或任何其他技巧,但我就是这样做的。有时如果循环内还有其他事情要做,我希望代码更具可读性,我会写
double val = x[i];
sum += (val == val ? val : 0);
//...
在循环内并在需要时重用 val
。
答案 12 :(得分:0)
std::accumulate
可能存在溢出问题,因此最好的方法是对较大的数据类型变量进行基于范围的累加以避免溢出问题。
long long sum = 0;
for (const auto &n : vector)
sum += n;
然后使用 static_cast<>
进一步向下转换为适当的数据类型。
答案 13 :(得分:-3)
很容易。 C ++ 11提供了一种总结矢量元素的简便方法。
sum = 0;
vector<int> vec = {1,2,3,4,5,....}
for(auto i:vec)
sum+=i;
cout<<" The sum is :: "<<sum<<endl;