一、accumulate用法
1、求一个区间的和、积(默认)
// 建立一个list,放一些double进去
list<double> ld;
...
// 计算它们的和,从0.0开始
double sum = accumulate(ld.begin(), Id.end(), 0.0);
在本例中,注意初始值指定为0.0,不是简单的0。这很重要。0.0的类型是double,所以accumulate内部使用了一个double类型的变量来存储计算的和。
如果这么写这个调用:
// 计算它们的和,从0开始;这不正确!
double sum = accumulate(ld.begin(), Id.end(), 0);
如果初始值是int 0,所以accumulate内部就会使用一个int来保存它计算的值。那个int最后变成accumulate的返回值,而且它用来初始化和变量。这代码可以编译和运行,但和的值可能不对。不是保存真的double的list的和,它可能保存了所有的double加起来的结果,但每次加法后把结果转换为一个int。
accumulate只需要输入迭代器,所以你甚至可以使用istream_iterator和istreambuf_iterator。
// 打印cin中那些int的和
cout << "The sum of the ints on the standard input is"
<< accumulate(istream_iterator<int>(cin), istream_iterator<int>(), 0);
2、自定义求和方式
比如,考虑怎么使用accumulate来计算容器中的字符串的长度和。
string::size_type
stringLengthSum(string::size_type sumSoFar, const string& s){
return sumSoFar + s.size();
}
这个函数的函数体非常简单,但你可能发现自己陷于string::size_type的出现。不要那样。每个标准STL容器都有一个typedef叫做size_type,那是容器计量东西的类型。比如,这是容器的size函数的返回类型。对于所有的标准容器,size_type必须是size_t,对于标准容器,你可以把Container::size_type看作size_t写法的一个奇异方式。
// 建立字符串的容器, 进行一些操作
set<string> ss;
...
// 把lengthSum设为对ss中的每个元素调用stringLengthSum的结果
//使用0作为初始统计值
string::size_type lengthSum = accumulate(ss.begin(), ss.end(),0, stringLengthSum);
3、求积
// 建立float的容器
vector<float> vf;
// 进行一些操作
...
// 把product设为对vf中的每个元素调用multiplies<float>(标准乘积仿函数类)的结果,
//用1.0f 作为初始统计值
float product = accumulate(vf.begin(), vf.end(), 1.0f, multiplies<float>());
4、求平均值
寻找point的区间的平均值
struct Point {
Point(double initX, double initY): x(initX), y(initY) {}
double x, y;
};
class PointAverage : public binary_function<Point, Point, Point> {
public:
PointAverage(): numPoints(0), xSum(0), ySum(0) {}
const Point operator()( const Point& avgSoFar, const Point& p ) {
++numPoints;
xSum += p.x;
ySum += p.y;
return Point(xSum/numPoints, ySum/numPoints);
}
private:
size_t numPoints;
double xSum;
double ySum;
};
list<Point> lp;
...
// 对Ip中的point求平均值
Point avg = accumulate(lp.begin(), lp.end(), Point(0, 0), PointAverage());
二、for_each用法
// 同上
struct Point {...);
class PointAverage : public unary_function<Point, void> {
public:
PointAverage(): xSum(0), ySum(0), numPoints(0) {}
void operator()(const Point& p){
++numPoints;
xSum += p.x;
ySum += p.y;
}
Point result() const {
return Point(xSum/numPoints, ySum/numPoints);
}
private:
size_t numPoints;
double xSum;
double ySum;
};
list<Point> Ip;
...
Point avg = for_each( lp.begin(), lp.end(), PointAverage() ).result;