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,这显然是错误的。有什么解释吗?
答案 0 :(得分:54)
您应该写下以下内容:
std::cout <<
std::accumulate ( doublenumbers.begin( ) , doublenumbers.end( ) , 0.0 ) ;
因为0的类型是int
。
当std::accumulate
实例化时,第三个参数的类型为int
,那么它将转换总和的右侧。 e.g:
result += *iter;
// int += double
这会强制转换double
到int
,而不是你想到的是相反的。
答案 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 int
或long 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))