반응형

accumulate 사용법과 주의사항

 

INTRO

C++ 에서 알고리즘을 공부하다가 accumulate 함수를 발견했습니다.

생각보다 편리한 기능이고 사용하기도 편했어요.

간편하게 배열의 합을 구할 수 있습니다.

 

2. 헤더 정보

#include <numeric> 를 include 하시면 됩니다.

 

3. 기본 사용법
#include <iostream>
#include <vector>
#include <numeric>
#include <string>
#include <functional>
 
int main()
{
    std::vector<int> v{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
 
    int sum = std::accumulate(v.begin(), v.end(), 0);
 
    int product = std::accumulate(v.begin(), v.end(), 1, std::multiplies<int>());
 
    auto dash_fold = [](std::string a, int b) {
                         return std::move(a) + '-' + std::to_string(b);
                     };
 
    std::string s = std::accumulate(std::next(v.begin()), v.end(),
                                    std::to_string(v[0]), // start with first element
                                    dash_fold);
 
    // Right fold using reverse iterators
    std::string rs = std::accumulate(std::next(v.rbegin()), v.rend(),
                                     std::to_string(v.back()), // start with last element
                                     dash_fold);
 
    std::cout << "sum: " << sum << '\n'
              << "product: " << product << '\n'
              << "dash-separated string: " << s << '\n'
              << "dash-separated string (right-folded): " << rs << '\n';
}
sum: 55
product: 3628800
dash-separated string: 1-2-3-4-5-6-7-8-9-10
dash-separated string (right-folded): 10-9-8-7-6-5-4-3-2-1

참고사이트에서 가져온 예제입니다.

예시와 결과값을 보면 와닿을 것입니다.

첫번째와 두번째는 first, last iterator이 들어가고 세번째 인자는 initial value of the sum 값이 들어갑니다.

 

4. 주의 사항
#include <iostream>
#include <vector>
#include <numeric>

using namespace std;

void main()
{
	vector<int> v{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

	cout << accumulate(v.begin(), v.end(), 0) << endl;

	vector<long long> v2{ 1'000'000'000, 2'000'000'000, 3'000'000'000, 4'000'000'000 };

	cout << accumulate(v2.begin(), v2.end(), 0) << endl;

	cout << accumulate(v2.begin(), v2.end(), 0LL) << endl;
	
	return;
}
55
1410065408
10000000000

여기서 세 번째 인자 '합의 초기값(initial value of the sum)'이 어떤 역할을 하는지 알 수 있습니다.

 

첫번째 예시의 경우는 int형으로 범위를 초과하지 않아 제대로 출력되고 있습니다.

 

그러나, 두번째 예시의 경우! 쓰레기값이 출력됩니다.

 

세번째 예시의 경우는 초기값을 잘 설정했을 경우, 제대로 나오는 것을 볼 수 있습니다.

 

즉, 범위를 초과하는 값들을 더할때는 초기값을 잘 설정해주어야하고,

 

이러한 문제가 발생한 이유는 accumlate의 반환값이 initial value의 타입을 따라 가기 때문입니다.

 

어떠한 경고도 뜨지 않고 자동으로 캐스팅되기때문에 주의할 필요가 있습니다.

template<class InputIt, class T>
constexpr // since C++20
T accumulate(InputIt first, InputIt last, T init)
{
    for (; first != last; ++first) {
        init = std::move(init) + *first; // std::move since C++20
    }
    return init;
}

참고 사이트에서 가져온 함수 원형 첫번째 버전입니다.

여기를 보면 템플릿으로 반환값이 init과 동일한 것을 볼 수 있습니다.

 

5. 참고 사이트

https://en.cppreference.com/w/cpp/algorithm/accumulate

반응형

'C, C++' 카테고리의 다른 글

[C/C++]explicit  (0) 2021.12.01
[C/C++]스마트 포인터(smart pointer)  (0) 2021.11.22
[C/C++] stringstream 사용법  (0) 2021.07.03
[C/C++]enum과 enum class  (0) 2021.04.05
[C/C++] 다형성 - 가상 함수  (0) 2020.09.10

+ Recent posts