356

What are the good ways of finding the sum of all the elements in a std::vector?

Suppose I have a vector std::vector<int> vector with a few elements in it. Now I want to find the sum of all the elements. What are the different ways for the same?

noɥʇʎԀʎzɐɹƆ
  • 9,967
  • 2
  • 50
  • 67
Prasoon Saurav
  • 91,295
  • 49
  • 239
  • 345
  • 2
    "How many"? Really? That seems an overly vague question. :p Might be more useful to ask for *a good* way to do it. – jalf Jul 11 '10 at 07:17
  • 5
    What do you mean when you say "function similar to?" Are you looking for a replacement for `std::accumulate` in Boost? (If so, why?) Are you looking for functions that do something similar to `std::accumulate`? (If so, what?) – James McNellis Jul 13 '10 at 13:02
  • 4
    If you want something similar to `std::accumulate`, presumably you also want it to be different in some respect (otherwise you could just use `std::accumulate`); what difference(s) from `std::accumulate` are you looking for? – CB Bailey Jul 14 '10 at 12:33
  • 1
    None of the solutions currently posted is safe, since `int` (and even `long long`) addition can overflow, which is undefined behavior. Better to use unsigned addition: `std::accumulate(v.begin(), v.end(), 0u)` – Jason Orendorff Sep 17 '22 at 13:37

13 Answers13

592

Actually there are quite a few methods.

int sum_of_elems = 0;

C++03

  1. Classic for loop:

     for(std::vector<int>::iterator it = vector.begin(); it != vector.end(); ++it)
         sum_of_elems += *it;
    
  2. Using a standard algorithm:

     #include <numeric>
    
     sum_of_elems = std::accumulate(vector.begin(), vector.end(), 0);
    

    Important Note: The last argument's type is used not just for the initial value, but for the type of the result as well. If you put an int there, it will accumulate ints even if the vector has float. If you are summing floating-point numbers, change 0 to 0.0 or 0.0f (thanks to nneonneo). See also the C++11 solution below.

C++11 and higher

  1. b. Automatically keeping track of the vector type even in case of future changes:

     #include <numeric>
    
     sum_of_elems = std::accumulate(vector.begin(), vector.end(),
                                    decltype(vector)::value_type(0));
    
  2. Using std::for_each:

     std::for_each(vector.begin(), vector.end(), [&] (int n) {
         sum_of_elems += n;
     });
    
  3. Using a range-based for loop (thanks to Roger Pate):

     for (auto& n : vector)
         sum_of_elems += n;
    

C++17 and above

  1. Using std::reduce which also takes care of the result type, e.g if you have std::vector<int>, you get int as result. If you have std::vector<float>, you get float. Or if you have std::vector<std::string>, you get std::string (all strings concatenated). Interesting, isn't it?

    auto result = std::reduce(v.begin(), v.end());
    

    There are other overloads of this function which you can run even parallelly, in case if you have a large collection and you want to get the result quickly.

Nawaz
  • 353,942
  • 115
  • 666
  • 851
Prasoon Saurav
  • 91,295
  • 49
  • 239
  • 345
  • 8
    Of course in C++03 you can use `std::for_each` with a functor, it just takes more lines of code to define than the C++0x lambda. – Ben Voigt Jul 11 '10 at 04:04
  • 8
    Why do your lambda examples use `for_each`? `accumulate` would be more concise (even if it doesn't need the lambda) – jalf Jul 11 '10 at 07:15
  • 4
    @jalf: your point is correct, I should have used `accumulate` inside `for_each` but isn't this example useful(for learning purpose) as it shows that we can also have nested lambdas :-) – Prasoon Saurav Jul 11 '10 at 07:37
  • @Prasoon: true. I was just worried that it might give some people the idea that lambas only work with `for_each`. – jalf Jul 11 '10 at 08:14
  • Can someone explain what does case 4 add to case 3? Is there more to it than wrapping the operation in a function? – Amnon Jul 11 '10 at 11:24
  • @Amnon: `Is there more to it than wrapping the operation in a function? ` Nopes, the example was just to show that lambdas can be nested inside the other as I have mentioned in my last comment. – Prasoon Saurav Jul 11 '10 at 11:29
  • You missed the most obvious – and, IMHO, the most natural – [0x-only solution](http://stackoverflow.com/questions/3221812/sum-of-elements-in-a-vector/3224488#3224488). :) –  Jul 11 '10 at 20:20
  • You missed the vanilla (non-iterator) for loop! – bobobobo Aug 20 '10 at 12:52
  • 104
    **Be careful** with `accumulate`. The last argument's type is used not just for the initial value, but for the type of the result. If you put an `int` there, it will accumulate `int`s even if the vector has `float`. The result can be subtly wrong, and the compiler will cast the result back up to a float without telling you. – nneonneo Feb 19 '13 at 03:30
  • It is better when using a range based for loop to pass by a `const` reference, particularly when you are not changing any elements in the iterated container. Your example above copies each element to a temporary variable first wich adds significant overhead. For example use `for (int const &n : vector)` or perhaps a more future proof version `for (auto const &n : vector)` . It is possible that your compiler is intelligent enough to make this optimisation anyway however it should not be relied upon. – silvergasp Jan 07 '16 at 00:26
  • 3
    Why would you use `for_each` if you have `accumulate`? – juanchopanza Feb 11 '16 at 19:44
  • @nneonneo: Thank you!! Wow. just wow! I personally believe the compiler must use the type of the given range and cast the last parameter to it, not the other way around. Besides that, why the compiler **doesn't even tell** about this implicit conversion from double/float to int? – Isaac Dec 15 '16 at 04:42
  • @Isaac: because this is just how `accumulate` is implemented - as essentially `decltype(initial) accum = initial; for(auto i : vec) accum += i; return accum;`. Doing `int += float` doesn't warn. – nneonneo Dec 15 '16 at 13:16
  • @juanchopanza Perhaps you are already going through the vector with `for_each`, and thus you can combine two things in one. – v010dya Nov 13 '21 at 08:46
  • I would also add that if you're using `std::accumulate` over a container with unsigned types, you can `std::numeric_limits` to get zero: https://en.cppreference.com/w/cpp/types/numeric_limits/min – Raleigh L. Feb 11 '22 at 19:19
  • How does this handle `nan`s in the vector? I have a vector of doubles, some of which might be NaN. I want to obviously ignore those values when summing – Jinx Nov 28 '22 at 19:39
  • I really wonder why C++ doesn't have simple `x.sum()`. How hard could it be to implement? – Peaceful Aug 12 '23 at 03:23
80

The easiest way is to use std:accumulate of a vector<int> A:

#include <numeric>
cout << accumulate(A.begin(), A.end(), 0);
beahacker
  • 1,660
  • 14
  • 10
  • To get the average, should I do `accumulate(A.begin(), A.end(), 0)/A.size();` or there is a special function just for that also? – KcFnMi Feb 08 '23 at 16:17
  • Hi @KcFnMi, you might be correct! According to this https://stackoverflow.com/questions/9334185/how-to-get-an-average-in-c – beahacker Mar 08 '23 at 11:07
32

Prasoon has already offered up a host of different (and good) ways to do this, none of which need repeating here. I'd like to suggest an alternative approach for speed however.

If you're going to be doing this quite a bit, you may want to consider "sub-classing" your vector so that a sum of elements is maintained separately (not actually sub-classing vector which is iffy due to the lack of a virtual destructor - I'm talking more of a class that contains the sum and a vector within it, has-a rather than is-a, and provides the vector-like methods).

For an empty vector, the sum is set to zero. On every insertion to the vector, add the element being inserted to the sum. On every deletion, subtract it. Basically, anything that can change the underlying vector is intercepted to ensure the sum is kept consistent.

That way, you have a very efficient O(1) method for "calculating" the sum at any point in time (just return the sum currently calculated). Insertion and deletion will take slightly longer as you adjust the total and you should take this performance hit into consideration.

Vectors where the sum is needed more often than the vector is changed are the ones likely to benefit from this scheme, since the cost of calculating the sum is amortised over all accesses. Obviously, if you only need the sum every hour and the vector is changing three thousand times a second, it won't be suitable.

Something like this would suffice:

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

Obviously, that's pseudo-code and you may want to have a little more functionality, but it shows the basic concept.

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • 7
    interesting, but be careful as `std::vector` isn't meant for subclassing. – Evan Teran Jul 11 '10 at 04:50
  • 7
    Sorry, I should have been clearer - you could create your own class with the same methods as vector which maintained a `has-a` vector within it, rather than being a proper subclass (`is-a`). – paxdiablo Jul 11 '10 at 05:08
  • @paxdiablo: Very nice with the `has-a`. – Matt Joiner Nov 14 '10 at 07:02
  • 1
    This is problematic unless you disable the accessors into the data, including but not limited to `operator[](int)`, non-const iterators... – David Rodríguez - dribeas Dec 02 '10 at 19:25
  • Not sure what you mean, @David, you won't _have_ access to the actual vector, it will be a private member of your own class. Any accesses/changes will have to be through functionality provided by your class so you will be able to intercept all use of the underlying vector. – paxdiablo Dec 02 '10 at 22:32
  • 1
    @paxdiablo I believe David means if the data stored in the vector is manipulated through the use of operator[] or indirecting through a non-const iterator. The value at the manipulated position will now be different which will make the sum incorrect. There's no way to assure the sum is correct if client code is ever able to hold a mutable reference to any element within the "subclassed" vector. – Bret Kuhns Sep 04 '12 at 03:21
  • That makes sense, but surely that's just a matter of providing the `operator[]` or iterator over the `UberVector` object rather than the `Vector` member. The whole point is to protect the vector from outside changes so the sum is always consistent with the data. If you expose the internal vector somehow, all bets are off. – paxdiablo Sep 04 '12 at 03:39
  • 2
    This approach causes performance penalty for basic vector operations. – Basilevs Sep 04 '12 at 09:11
  • `has-a` over `is-a` is synonymous to the maxim "prefer composition over inheritance," and is discussed further here: https://stackoverflow.com/questions/49002/prefer-composition-over-inheritance – llf Jul 11 '18 at 17:56
  • @Basilevs: yes it will have an cost. The question is, does that cost outweigh the benefits? What you'll most likely be looking at is a single extra layer of call to the underlying vector, there'll be no extra checks taking place or anything like that. I'll note, as one example, that smart pointers *also* have a cost but the chances of me going back to the bad old days of raw pointers is very slim :-) Basically, if the benefit of having a constant-time `sum()` function are worth more than the cost, use this solution. If not, calculate the sum each time. – paxdiablo Nov 05 '18 at 03:26
25

Why perform the summation forwards when you can do it backwards? Given:

std::vector<int> v;     // vector to be summed
int sum_of_elements(0); // result of the summation

We can use subscripting, counting backwards:

for (int i(v.size()); i > 0; --i)
    sum_of_elements += v[i-1];

We can use range-checked "subscripting," counting backwards (just in case):

for (int i(v.size()); i > 0; --i)
    sum_of_elements += v.at(i-1);

We can use reverse iterators in a for loop:

for(std::vector<int>::const_reverse_iterator i(v.rbegin()); i != v.rend(); ++i)
    sum_of_elements += *i;

We can use forward iterators, iterating backwards, in a for loop (oooh, tricky!):

for(std::vector<int>::const_iterator i(v.end()); i != v.begin(); --i)
    sum_of_elements += *(i - 1);

We can use accumulate with reverse iterators:

sum_of_elems = std::accumulate(v.rbegin(), v.rend(), 0);

We can use for_each with a lambda expression using reverse iterators:

std::for_each(v.rbegin(), v.rend(), [&](int n) { sum_of_elements += n; });

So, as you can see, there are just as many ways to sum the vector backwards as there are to sum the vector forwards, and some of these are much more exciting and offer far greater opportunity for off-by-one errors.

Jonas
  • 6,915
  • 8
  • 35
  • 53
James McNellis
  • 348,265
  • 75
  • 913
  • 977
  • 39
    And why not also cycle through the vector by adding a prime number with the modulus operator for wraparound? :-) – paxdiablo Jul 11 '10 at 05:17
  • 3
    @paxdiablo You only really need to be relatively prime to `v.size()`. – clstrfsck Jul 13 '10 at 04:55
  • msandiford: not only. @paxdiablo: you need to be realtively prime if you want to access all elements. stepping +7 in a vector of size 7 wont give you much... – Moberg Feb 05 '14 at 10:06
  • 1
    -1: vector::size() returns an unsigned value, making expressions like (v.size() - 1) generate warnings, or a minefield in worst cases. – Julien Guertault Apr 23 '14 at 06:19
  • 2
    Why does this answer exist? Is there an advantage to summing backwards, or are you just trolling? – Lynn Mar 14 '17 at 20:39
  • 4
    @Lynn: If the end of the vector is hot in cache (from a previous loop that went forwards), then yes, looping backwards can be measurably faster on current Intel x86 CPUs. Also, counting a loop-counter down to zero can save the compiler an instruction in the asm, which can be significant if it doesn't unroll the loop. Prefetching sometimes works slightly better when looping forwards, though, so in general it's not better to always loop backwards. – Peter Cordes Jul 30 '17 at 06:10
  • A small advantage of counting backwards: `for (int i(v.size()); i--; ) sum_of_elements += v[i]` saves the comparison `i < 0`, with a small performance gain – Martin Smith Feb 23 '22 at 12:51
  • You don't have to keep getting the value of ``.size();`` which the compiler may not understand doesn't vary. – CodeLurker Jan 22 '23 at 07:44
18
#include<boost/range/numeric.hpp>
int sum = boost::accumulate(vector, 0);
rafak
  • 5,501
  • 2
  • 19
  • 30
  • Thanks for the answer. BTW what is the difference between std::accumulate and boost::accumulate in time complexity? – Prasoon Saurav Aug 15 '10 at 08:56
  • 1
    The time complexity is the same for std's and boost's accumulate -- linear. In this case, boost::accumulate is just easier to type than sending in the begin and end manually. There's no real difference. – metal Sep 11 '10 at 15:16
  • 7
    `boost::accumulate` is just a wrapper around `std::accumulate`. – rafak Sep 15 '10 at 10:15
  • 2
    The non-boost way is not much harder: `#include ` and `std::accumulate(v.begin(), v.end(), (int64_t)0);`. Notice that the type of the initial accumulator value is used as the accumulator type, so if you want to sum 8-bit elements into a 64-bit result, that's how you do it. – Peter Cordes Jul 30 '17 at 06:14
10

One can also use std::valarray<T> like this

#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;
}

Some may not find this way efficient since the size of valarray needs to be as big as the size of the vector and initializing valarray will also take time.

In that case, don't use it and take it as yet another way of summing up the sequence.

JeJo
  • 30,635
  • 6
  • 49
  • 88
NeutronStar
  • 220
  • 1
  • 4
  • 17
7

C++0x only:

vector<int> v; // and fill with data
int sum {}; // or = 0 ... :)
for (int n : v) sum += n;

This is similar to the BOOST_FOREACH mentioned elsewhere and has the same benefit of clarity in more complex situations, compared to stateful functors used with accumulate or for_each.

  • 5
    If you change `for (int n : v) sum += n;` into `for (auto n : v) sum += n;` it will work with any vector template. I known OP referes to vector, but this way is slightly more general :-) – Jonas Oct 20 '14 at 12:10
4

I'm a Perl user, an a game we have is to find every different ways to increment a variable... that's not really different here. The answer to how many ways to find the sum of the elements of a vector in C++ is probably an infinity...

My 2 cents:

Using BOOST_FOREACH, to get free of the ugly iterator syntax:

sum = 0;
BOOST_FOREACH(int & x, myvector){
  sum += x;
}

iterating on indices (really easy to read).

int i, sum = 0;
for (i=0; i<myvector.size(); i++){
  sum += myvector[i];
}

This other one is destructive, accessing vector like a stack:

while (!myvector.empty()){
   sum+=myvector.back();
   myvector.pop_back();
}
kriss
  • 23,497
  • 17
  • 97
  • 116
  • Why do you say iterating on indices is inefficient? What's your basis for saying that? – bobobobo Aug 20 '10 at 12:53
  • @bobobobo: well, inefficient is probably excessive. You have both to compute effective data position from vector and increment counter but one of these two operations should be enough, but cost of dereferencing iterators may even be worse. Hence I will remove the word. – kriss Aug 20 '10 at 13:28
  • An optimizing compiler can optimize away the index variable and just use a pointer increment if it wants to. (It can make the loop-exit condition be a pointer-comparison against `start + length`). Actual iterators should also optimize away entirely. Remember, it's not perl; it's fully compiled to asm, not interpreted. – Peter Cordes Jul 30 '17 at 06:18
3

Using inclusive_scan (C++17 and above):

The advantage is you can get sums of first "N" elements in a vector. Below is the code. Explanation in comments.

To use inclusive_scan , need to include "numeric" header.

    //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;

Also there is an overload where the execution policy can be specified. Sequential execution or Parallel execution. Need to include "execution" header.

    //SUM ALL NUMBERS IN A GIVEN VECTOR.
    inclusive_scan(std::execution::par,data.begin(), data.end(),
        sums.begin());

Using reduce :

One more option which I did not notice in the answers is using std::reduce which is introduced in c++17.

But you may notice many compilers not supporting it (Above GCC 10 may be good). But eventually the support will come.

With std::reduce, the advantage comes when using the execution policies. Specifying execution policy is optional. When the execution policy specified is std::execution::par, the algorithm may use hardware parallel processing capabilities. The gain may be more clear when using big size vectors.

Example:

//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;

You need <numeric> header for std::reduce. And '<execution>' for execution policies.

Pavan Chandaka
  • 11,671
  • 5
  • 26
  • 34
2
 #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);
    }
hey dude
  • 21
  • 1
1

std::accumulate could have overflow issues so the best approach could be to do range based accumulation on bigger data type variable to avoid overflow issues.

long long sum = 0;
for (const auto &n : vector)
  sum += n;

And then downcast to appropriate data type further using static_cast<>.

0

Nobody seems to address the case of summing elements of a vector that can have NaN values in it, e.g. numerical_limits<double>::quite_NaN()

I usually loop through the elements and bluntly check.

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);

}

It's not fancy at all, i.e. no iterators or any other tricks but I this is how I do it. Some times if there are other things to do inside the loop and I want the code to be more readable I write

double val = x[i];

sum += (val == val ? val : 0);

//...

inside the loop and re-use val if needed.

OGCJN
  • 393
  • 3
  • 9
-5

It is easy. C++11 provides an easy way to sum up elements of a vector.

sum = 0; 
vector<int> vec = {1,2,3,4,5,....}
for(auto i:vec) 
   sum+=i;
cout<<" The sum is :: "<<sum<<endl; 
Nick
  • 138,499
  • 22
  • 57
  • 95