C ++ std :: accumulate没有给出预期的总和

时间:2010-08-30 21:46:06

标签: c++

double numbers[ ] = { 1, 0.5 ,0.333333 ,0.25 ,0.2, 0.166667, 0.142857, 0.125,
                       0.111111, 0.1 } ;
std::vector<double> doublenumbers ( numbers , numbers + 10 ) ;
std::cout << std::accumulate ( doublenumbers.begin( ) , doublenumbers.end( ) , 0 ) ;

这会产生1,这显然是错误的。有什么解释吗?

6 个答案:

答案 0 :(得分:54)

您应该写下以下内容:

std::cout << 
 std::accumulate ( doublenumbers.begin( ) , doublenumbers.end( ) , 0.0 ) ;

因为0的类型是int

std::accumulate实例化时,第三个参数的类型为int,那么它将转换总和的右侧。 e.g:

   result += *iter;
// int    += double

这会强制转换doubleint,而不是你想到的是相反的。

答案 1 :(得分:8)

您使用accumulate作为0参数调用init,因此它将使用整数数学进行累积。请改用0.0

答案 2 :(得分:5)

std::accumulate ( doublenumbers.begin( ) , doublenumbers.end( ) , .0 ) ;

std::accumulate ( doublenumbers.begin( ) , doublenumbers.end( ) , (double) 0 ) ;

“accumulator”变量的类型是std::accumulate的最后一个参数的类型。您提供了0作为参数 - int字面值 - 这意味着累加器将具有类型int。 “累积”在int累加器中完成(即在每次单独求和后舍入到int)并产生int结果。在这种情况下,它显然是1

答案 3 :(得分:3)

std::accumulate将开始对作为第三个参数传递的类型求和,如果传递一个整数,则返回类型将为int。并且在这种情况下隐式转换为double

在C ++ 11和C ++ 14 中,如果您想防止缩小转换,您可以使用 direct-list-initialization 创建对象:

double sum { std::accumulate(doublenumbers.begin(), doublenumbers.end(), 0) };

然后,编译器会给出一个警告,说明您正在尝试从int转换为double以及在哪一行转换。这将节省您的调试时间。您可以轻松修复它以使其变得正确:

double sum { std::accumulate(doublenumbers.begin(), doublenumbers.end(), 0.0) };

答案 4 :(得分:1)

std::accumulate<double> (doublenumbers.begin(), doublenumbers.end(), 0); // also works

答案 5 :(得分:1)

只想添加(也许)另一个有用的答案。

对于那些谁上了错误的总和unsigned long long intlong long int,则需要初始化值转换为特定类型。

std::accumulate(vec.begin(), vec.end(), (long long int) 0) // or (unsigned long long int)

也可以自动投基于向量类型:

std::accumulate(vec.begin(), vec.end(), decltype(vec)::value_type(0))