Do accumulate() function in C++ adds negative numbers?

545 views Asked by At
vector<int> nums={1,12,-5,-6,50,3};
int k=4;
int n=nums.size();
for(int i=0;i<=n-k;i++)
    cout<<accumulate(nums.begin()+i,nums.begin()+i+k-1,0)<<" ";

The output of the above code is: 8 1 39

The question is why sum of [1,12,-5,-6] is 8, which should be 2=(1+12-5-6) ?

Same for 1, which should be 51=(50+12-5-6), and

Same for 39, which should be 42=(50+3-6-5)?

3

There are 3 answers

0
Bathsheba On

If your hypothesis is that std::accumulate doesn't treat negative numbers in the conventional way, then test it directly

#include <iostream>
#include <vector>
#include <numeric>

int main() {
    std::vector<int> nums={1,12,-5,-6,50,3};
    std::cout << std::accumulate(nums.begin(), nums.begin() + 4, 0);
}

The output is 2, corresponding to 1 + 12 - 5 - 6.

The issue is in your code; and in your iterator addition. Specifically, the first two parameters of std::accumulate are both relative to nums.begin(): you need to drop the -1 from the second parameter.

0
MikeCAT On

The second argument of std::accumulate is the position just after the last element to deal with.

The -1 in nums.begin()+i+k-1 is preventing the last element to deal with from being processed, so you should remove that.

0
molbdnilo On

If you actually do what accumulate does - add sequentially - and look at each partial result, you will see

1 + 0 = 1
1 + 12 = 13
13 + -5 = 8
8 + -6 = 2

12 + 0 = 12
12 + -5 = 7
7 + -6 = 1
1 + 50 = 51

-5 + 0 = -5
-5 + -6 = -11
-11 + 50 = 39
39 + 3 = 42

At this point you might spot that accumulates result is the sum of the first three numbers, not four.
Then you exclaim loudly that there's a bug in accumulate that makes it disregard the last element.
And then you look at the documentation and notice that the end of the range is "one past the last element", so your end iterator, nums.begin() + i + 4 - 1, says that the element before it (that is, *(begin() + i + 2), the third element from begin() + i) is the last element inside the range.
All iterator ranges (and index intervals) in the standard library are half-open in this manner.

The solution is to remove the -1 from the end iterator.