Подтвердить что ты не робот

С++ std:: accumulate не дает ожидаемой суммы

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, что, очевидно, неверно. Любые объяснения?

4b9b3361

Ответ 1

Вы должны написать следующее:

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

Поскольку тип 0 равен int.

Когда std::accumulate создается с типом третьего аргумента int, он преобразует правую часть суммы. например:.

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

Это приведет к преобразованию double в int, а не к тому, что вы думаете о том, что противоположно.

Ответ 2

Вы вызываете accumulate с 0 в качестве аргумента init, поэтому он будет накапливаться с использованием целочисленных математических вычислений. Вместо этого используйте 0.0.

Ответ 3

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

или

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

Тип переменной "аккумулятора" является типом последнего аргумента std::accumulate. Вы предоставили 0 в качестве аргумента - литерал int - это означает, что аккумулятор будет иметь тип int. "Накопление" выполняется в аккумуляторе int (т.е. округляется до int после каждого отдельного суммирования) и выдает результат int. В этом случае это, по-видимому, 1.

Ответ 4

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

Ответ 5

std::accumulate начнет суммировать тип, который передается как третий аргумент, если вы передадите целое число, тип возврата будет int. И в этом случае неявно преобразован в double.

В С++ 11 и С++ 14, если вы хотите предотвратить сужение преобразования, вы можете создать объект, используя прямой список инициализация:

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

Затем компилятор даст вам предупреждение о том, что вы пытаетесь преобразовать из int в double, а также в какую строку. Это позволит сэкономить время отладки. И вы можете легко исправить это, чтобы оно стало правильным:

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