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