STLのaccumulate()を使うときはオーバーフローに気をつける


このエントリーをはてなブックマークに追加

STLにはvectorの各要素の数の和を出力するaccumulate()という便利関数があるが、気をつけないとオーバーフローによりはまってしまう。その例として以下のコードを見ていただきたい。コードの意図は、1000000000 + 1000000001 + ... + 1000000009を計算してsumに格納することである。

#include <iostream>
#include <vector>
#include <numeric>

using namespace std;

int main(){

    vector<long long> nums;
    for(int i = 0; i < 10; ++i){
        nums.push_back( (i + 1000000000) );
        cout << nums[i] << endl;
    }

    long long sum = accumulate(nums.begin(), nums.end(), 0);
    cout << "-----" << endl;
    cout << "sum = " << sum << endl;

    return 0;
}

しかしこのコードでは、意図に反して

-----
sum = 1410065453
-----

という結果を出してしまう。

この原因は、accumulateの第三引数(数値の合計に下駄をはかせる値)に0と書いてしまったことにある。この0がint型とみなされるせいで、数列の和がint型で計算されてしまう。

意図通りに動かすには、accumulateの第三引数を0LLと書き、long long型の整数であることを明示する必要がある。

-----
long long sum = accumulate(nums.begin(), nums.end(), 0LL);
-----

このように修正することで、意図通りの結果が得られた。

-----
sum = 10000000045
-----

修正後のコード全文はこちら