Why is the std::accumulate function showing the wr

2019-01-14 22:05发布

问题:

Consider the following code for adding all the elements of a vector:

#include<iostream>
#include<algorithm>
#include<numeric>
#include<vector>
using namespace std;
int main(void)
{

   std::vector<double> V;
   V.push_back(1.2);
   V.push_back(3.6);
   V.push_back(5.6);
   double sum = accumulate(V.begin(),V.end(),0);

   cout << "The sum of the elements of the vector V is " << sum << endl;
   return 0;
}

When I compile this on Cygwin on Windows and run it, I get the output at the terminal as

The sum of the elements of the vector V is 9

The accumulate function seems to be rounding down all the numbers and adding them up, which would explain the answer.

Is this something wrong with the Cygwin g++ compiler, or my misinterpretation of the accumulate function for adding up a vector of doubles?

回答1:

std::accumulate is declared as such:

template <typename InputIt, typename T>
T accumulate(InputIt first, InputIt last, T init);

The second template argument to std::accumulate is deduced as int because 0 is of type int. Pass a double instead, like 0.0.



回答2:

Change 0 to 0.0. It then gets 10.4 for me. While the container is double, the type deduction is int because of the initial argument passed to std::accumulate. Therefore, the container is assigned int values.



回答3:

The value being returned from the std::accumulate function is an integer, not a double because of this:

double sum = accumulate(V.begin(), V.end(), 0);
//                                          ^-- Integer!

The template parameter inference done by the C++ compiler makes the return type of the accumulate function the same as the init parameter, which in your case is an integer. Therefore the return value is being rounded to the nearest whole number. The return value is then being implicitly cast back into a double when it's assigned into sum.

To fix this, you can simply pass the zero as a double (i.e. 0.0) instead.



回答4:

The last argument of the std::accumulate call determines the type of the internal sum as well as the return type. Since 0 is an int everything gets rounded down during addition, and the result is an integer as well.