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

use*_*354 37 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 ) ;
Run Code Online (Sandbox Code Playgroud)

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

Ara*_*raK 59

你应该写下面的内容:

std::cout << 
 std::accumulate ( doublenumbers.begin( ) , doublenumbers.end( ) , 0.0 ) ;
Run Code Online (Sandbox Code Playgroud)

因为0的类型是int.

std::accumulate使用第三个参数的类型进行实例化时int,则会转换总和的右侧.例如:

   result += *iter;
// int    += double
Run Code Online (Sandbox Code Playgroud)

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

  • 有趣的是,即使使用"0.0",由于浮动数字的近似表示,仍然可能存在一些差异(对于大数额).`std :: vector <float> v(1000,1000.1f); std :: cout << std :: accumulate(v.begin(),v.end(),0.0f);`产生`1.00011e + 06`因为float在我的机器上只有5/6位数的精度. (3认同)
  • 我只是遇到同样的问题.现在我只是想知道,如何从文档中了解这一点(例如http://en.cppreference.com/w/cpp/algorithm/accumulate)?这是一个严肃的问题而不是抱怨.我真的很想习惯C++. (2认同)

Oli*_*rth 8

你打电话accumulate0作为init参数,所以它会积聚使用整数数学.请0.0改用.


AnT*_*AnT 6

std::accumulate ( doublenumbers.begin( ) , doublenumbers.end( ) , .0 ) ;
Run Code Online (Sandbox Code Playgroud)

要么

std::accumulate ( doublenumbers.begin( ) , doublenumbers.end( ) , (double) 0 ) ;
Run Code Online (Sandbox Code Playgroud)

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


And*_* DM 6

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

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

double sum { std::accumulate(doublenumbers.begin(), doublenumbers.end(), 0) };
Run Code Online (Sandbox Code Playgroud)

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

double sum { std::accumulate(doublenumbers.begin(), doublenumbers.end(), 0.0) };
Run Code Online (Sandbox Code Playgroud)