SGI专属power(),iota()方法
// file: 6numeric.cpp #include <numeric> #include <vector> #include <fucntional> #include <iostream> #include <iterator> // ostream_iterator #include <algorithm> using namespace std; int main() { int ia[5] = {1,2,3,4,5}; vector<int> iv(ia,ia+5); cout << accumulate(iv.begin(),iv.end(),0) << endl; // 15,i.e. 0 + 1 + 2 + 3 + 4 + 5 cout << accumulate(iv.begin(),iv.end(),0,minus<int>()) << endl; // -15,i.e. 0 - 1 - 2 - 3 - 4 - 5 cout << inner_product(iv.begin(),iv.end(),iv.begin(),10) << endl; // 65,i.e 10 + 1*1 + 2*2 + 3*3 + 4*4 + 5*5 cout << inner_product(iv.begin(),iv.end(),iv.begin(),10,minus<int>(),plus<int>()) << endl; // -20,i.e. 10 - 1+1 - 2+2 - 3+3 - 4+4 - 5+5 // 以下的这个迭代器将绑定到cout,作为输出用 ostream_iterator<int> oite(cout," "); partial_sum(iv.begin(),iv.end(),oite); // 1 3 6 10 15 (第n个元素是前n个元素的相加总计) partial_sum(iv.begin(),iv.end(),oite,minus<int>()); // 1 -1 -4 -8 -13 (第n个新元素是前n个旧元素的运算总计) adjacent_difference(iv.begin(),iv.end(),oite); // 1 1 1 1 1 (#1元素照录,#n新元素等于#n旧元素 - #n-1旧元素) adjacent_difference(iv.begin(),iv.end(),oite,plus<int>()); // 1 3 5 7 9 (#1元素照录,#n新元素等于op(#n旧元素,#n-1旧元素)) cout << power(10,3) << endl; // 1000 ,i.e 10*10*10 cout << power(10,3,plus<int>()) << endl; // 30,i.e,10+10+10 int n = 3; iota(iv.begin(),iv.end(),n); // 在指定区间内填入n,n+1,n+2... for (int i=0; i < iv.size(); ++ i) cout << iv[i] << ' '; // 3 4 5 6 7 return 0; }
这段代码摘自是《STL源码剖析》P298,但是无法通过编译,编译错误有2个
\P298\main.cpp||In function 'int main()':|
\P298\main.cpp|42|error: 'power' was not declared in this scope|
\P298\main.cpp|46|error: 'iota' was not declared in this scope|
\P298\main.cpp|47|warning: comparison between signed and unsigned integer expressions|
||=== Build finished: 2 errors, 1 warnings ===|
警告是很显然的,因为类型不匹配,如果将int转换成size_t就没有任何问题,这不是问题。
第一个错误:power没有声明,我们知道c语言中power的头文件是math.h,在C++中我们应该这么写#include <cmath>,我将#include <cmath> 加入代码中还是错的。很明显这里power的参数有仿函数,因此头文件显然不应该是cmath。于是乎我谷歌了一下还是没有结果,我就傻了,莫非他不是STL之中的函数,我在《STL源码剖析》目录中找到了power的那一节。
一看书我就知道了:
“power算法由SGI专属,不在STL标准之列。它用来计算某数的n幂次方。...”
之后的一节便是 :“iota算法由SGI专属,并不在STL标准之列。它用来设定某个区间的内容,时期内的每一个元素从指定的value值开始,呈现递增状态。”
这时候我才明白了,原来是这么回事!我还纳闷呢,听过"itoa",还没听过"iota",我还怀疑是书写错了。
那好吧,既然没定义,那就自定义一个吧,再说书上有源码,直接超过去就ok了。
下面是程序的最终版:
// file: 6numeric.cpp #include <numeric> #include <vector> #include <functional> #include <iostream> #include <iterator> // ostream_iterator #include <algorithm> using namespace std; // 版本2,幂次方,如果指定为乘法运算,则当n >= 0时返回x^n // 注意,“MonoidOperation”必须满足结合律(associative) // 但不需满足交换律 template <class T,class Interger,class MonoidOperation> T power(T x,Interger n,MonoidOperation op) { if (n == 0) // return identity_element(op); // 取出“证同元素”identity element // 张杰注释:以上代码error: 'identity_element' was not declared in this scope| // 可能也是版本的问题。因此,我就直接return x了,这不合理,但是我没有找到合理的解决方案 return x; else { while ((n&1) == 0) { n >>= 1; x = op(x,x); } T result = x; n >>= 1; while (n != 0) { x = op(x,x); if ((n & 1) != 0) result = op(result,x); n >>= 1; } return result; } } // 版本1,乘幂 template <class T,class Integer> inline T power(T x,Integer n) { return power(x,n,multiplies<T>()); //指定运算型为乘法 } // 函数意义:在[first,last)区间内填入value,value+1,value+2 template <class ForwardIterator,class T> void iota(ForwardIterator first,ForwardIterator last,T value) { while (first != last) * first ++ = value ++; } int main() { int ia[5] = {1,2,3,4,5}; vector<int> iv(ia,ia+5); cout << accumulate(iv.begin(),iv.end(),0) << endl; // 15,i.e. 0 + 1 + 2 + 3 + 4 + 5 cout << accumulate(iv.begin(),iv.end(),0,minus<int>()) << endl; // -15,i.e. 0 - 1 - 2 - 3 - 4 - 5 cout << inner_product(iv.begin(),iv.end(),iv.begin(),10) << endl; // 65,i.e 10 + 1*1 + 2*2 + 3*3 + 4*4 + 5*5 cout << inner_product(iv.begin(),iv.end(),iv.begin(),10,minus<int>(),plus<int>()) << endl; // -20,i.e. 10 - 1+1 - 2+2 - 3+3 - 4+4 - 5+5 // 以下的这个迭代器将绑定到cout,作为输出用 ostream_iterator<int> oite(cout," "); partial_sum(iv.begin(),iv.end(),oite); cout << endl; // 此行代码由张杰添加,便于显示 // 1 3 6 10 15 (第n个元素是前n个元素的相加总计) partial_sum(iv.begin(),iv.end(),oite,minus<int>()); cout << endl; // 此行代码由张杰添加,便于显示 // 1 -1 -4 -8 -13 (第n个新元素是前n个旧元素的运算总计) adjacent_difference(iv.begin(),iv.end(),oite); cout << endl; // 此行代码由张杰添加,便于显示 // 1 1 1 1 1 (#1元素照录,#n新元素等于#n旧元素 - #n-1旧元素) adjacent_difference(iv.begin(),iv.end(),oite,plus<int>()); cout << endl; // 此行代码由张杰添加,便于显示 // 1 3 5 7 9 (#1元素照录,#n新元素等于op(#n旧元素,#n-1旧元素)) cout << power(10,3) << endl; // 1000 ,i.e 10*10*10 cout << power(10,3,plus<int>()) << endl; // 30,i.e,10+10+10 int n = 3; iota(iv.begin(),iv.end(),n); // 在指定区间内填入n,n+1,n+2... for (int i=0; i < iv.size(); ++ i) cout << iv[i] << ' '; // 3 4 5 6 7 cout << endl; // 此行代码由张杰添加,便于显示 return 0; }
1、以上代码我进行修改的地方,都进行了注释,其他代码全部摘自侯捷《STL源码剖析》
2、以上代码通过code::blocks编译运行。其他IDE结果可能有所不同,其原因可能是因为STL的版本不同。