C++STL 求和:accumulate 【轉】


該算法在numeric頭文件中定義。

accumulate()的原型為(文件取自DEV-C++編譯器):

 1 template<typename _InputIterator, typename _Tp, typename _BinaryOperation>
 2  _Tp accumulate(_InputIterator __first, _InputIterator __last, _Tp __init,
 3             _BinaryOperation __binary_op)
 4  {
 5      // concept requirements
 6      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
 7     __glibcxx_requires_valid_range(__first, __last);
 8  
 9     for ( ; __first != __last; ++__first)
10        __init = __binary_op(__init, *__first);
11     return __init;
12  }

 

假設vec是一個int型的vector對象,下面的代碼:

//sum the elements in vec starting the summation with the value 42
int sum = accumulate(vec.begin() , vec.end() , 42);

將sum設置為vec的元素之和再加上42。

accumulate帶有三個形參:頭兩個形參指定要累加的元素范圍,第三個形參則是累加的初值

accumulate函數將它的一個內部變量設置為指定的初始值,然后在此初值上累加輸入范圍內所有元素的值。accumulate算法返回累加的結果,其返回類型就是其第三個實參的類型

 用於指定累加起始值的第三個參數是必要的,因為accumulate對將要累加的元素類型一無所知,除此之外,沒有別的辦法創建合適的起始值或者關聯的類型。 

accumulate對要累加的元素類型一無所知,這個事實有兩層含義。首先,調用該函數時必需傳遞一個初始值,否則,accumulate將不知道使用什么初始值。其次,容器內的元素類型必須與第三個實參的類型匹配,或者可轉換為第三個實參的類型。在accumulate內部,第三個實參用作累加的起點;容器內的元素按順序連續累加到綜合之中。因此,必須能夠將元素類型加到總和類型上。

 

假定V是vector<double>類型的對象,則調用accumulate(v.begin() , v.end() , 0)是否有錯?如果有的話,錯在哪里?

從函數調用上看沒有錯誤。
調用accumulate函數必須滿足的條件包括:容器內的元素類型必須與第三個實參的類型匹配,或者可轉換為第三個實參的類型。上述調用中的第三個實參為int類型,而vector對象中的元素的類型為double類型,可以轉換為int類型。

但計算的結果不准確。因為將double類型轉換為int類型會截去小數部分,得到的求和結果是各元素的整數部分的和,是一個int類型的值,與實際的元素值總和相比會有比較大的誤差。

 

考慮下面的例子,可以使用accumulate把string型的vector容器中的元素連接起來:

//concatenate elements from V and store in sum
string sum = accumulate(v.begin() , v.end() , string(" "));

這個函數調用的效果是:從空字符串開始,把vec里的每個元素連接成一個字符串。

 

下面讓我們用一個具體事例來說明:用accumulate統計vector<int>容器對象中的元素之和。

 1 //讀取一系列int型數據,並將它們存儲到vector對象中,
 2 //然后使用algorithm頭文件中定義的名為accumulate的函數,
 3 //統計vector對象中的元素之和
 4 #include<iostream>
 5 #include<vector>
 6 #include<numeric>
 7 using namespace std;
 8 
 9 int main()
10 {
11     int ival;
12     vector<int> ivec;
13 
14     //讀入int型數據並存儲到vector對象中,直至遇到文件結束符
15     cout<<"Enter some integers(Ctrl+z to end): "<<endl;
16     while(cin >> ival)
17         ivec.push_back(ival);
18 
19     //使用accumulate函數統計vector對象中的元素之和並輸出結果
20     cout<<"summation of elements in the vector: "
21         <<accumulate(ivec.begin() , ivec.end() , 0)  //統計vector對象中的元素之和
22         <<endl;
23 
24     return 0;
25 }

 

accumulate()可以用來直接計算數組或者容器中C++內置數據類型,但是對於自定義數據類型,我們就需要自己動手寫一個類來實現自定義數據的處理,然后讓它作為accumulate()的第四個參數。

假設自定義數據類型為:

1 struct Student  
2 {  
3       string name;   // 學生姓名  
4        int total;      // 四級分數  
5 };  
那么我們可能要定義如下列的類:

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <numeric>
 4 #include <vector>
 5 #include <string>
 6 using namespace std;
 7 
 8 struct Student
 9 {
10        string name;
11        int total;
12 };
13 
14 class PS{
15  public:
16         int operator()(int t1,const Student& t2)
17         {
18             return (t1 + t2.total);
19         }
20         
21 };
22 
23 int main()
24 {
25     Student student[3]={
26             {"hicjiajia",10},
27             {"sijikaoshi",20},
28             {"what",40}
29             };
30     
31     int sum=accumulate(&student[0],&student[3],0,PS());
32     cout<<sum<<endl;
33     
34     system("pause");
35     return 0;
36 }


文末附:資料鏈接


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM