找出std::vector中所有元素的和的好方法是什么?

假设我有一个向量std::vector<int> vector,其中有几个元素。现在我要求所有元素的和。同样的东西有什么不同的表达方式?


当前回答

我是一个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();
}

其他回答

也可以像这样使用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也需要时间。

在这种情况下,不要使用它,把它作为另一种对序列求和的方式。

似乎没有人能解决向量中可以有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。

使用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>'用于执行策略。

我是一个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<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);
    }