首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 开源 FAQ 第二书店 博文视点 程序员
频道: 研发 数据库 中间件 信息化 视频 .NET Java 游戏 移动 服务: 人才 外包 培训
    图书品种:235680
       
热门搜索: ASP.NET Ajax Spring Hibernate Java

7.5 数值积分

STL为很多复杂的算法提供基本的计算。使用STL,程序员可以方便地实现这些算法。下面以数值积分为例介绍STL对算法的支持。积分的思想是使用生成器产生一组点序列,其中生成器(generator)是一个类,它重载了函数调用运算符operator()。STL中的算法

generate(iterator b, iterator e, generator g)

为函数产生(0,1)区间的vector的值。程序中要用到algorithm、numeric和vector库。

文件 stl_integration1.cpp

// Simple integration routine for x * x over (0, 1)

#include <iostream>

#include <numeric>

#include <algorithm>

#include <vector>

using namespace std;

// The function is represented in class gen

class gen {             // generator for integrated function

public:

   gen(double x_zero, double increment)

      : x(x_zero), incr(increment) { }

      double operator()() { x += incr; return x * x; }

private:

   double x, incr;

};

double integrate(gen g, int n) // integrate on (0,1)

{

   vector<double> fx(n);

   generate(fx.begin(), fx.end(), g);

   return(accumulate(fx.begin(), fx.end(), 0.0) / n);

}

int main()

{

   const int n = 10000;

   gen g(0.0, 1.0/n);

   cout << "integration program x**2" << endl;

   cout << integrate(g, n) << endl;

}

stl_integration 程序解析

■ class gen { // generator for integrated function

 public:

    gen(double x_zero, double increment)

    : x(x_zero), incr(increment) { }

    double operator()() {x += incr; return x * x; }

 private:

    double x, incr;

 };

要编写一个生成器必须编写一个类来重载无参数的函数调用运算符。本例中gen::operator()()用来增加x的值,类构造函数用来初始化变量x以及增量incr。这里的基本思想是使用生成器生成一个值序列,使用这些值进行数值积分。

■ double integrate(gen g, int n) // integrate (0,1)

 {

     vector<double> fx(n);

我们使用生成器在0~1以1/n为步长进行积分。表达式x*x的值存储在向量fx中,其值在0~1(包括1)。

■ generate(fx.begin(), fx.end(), g);

生成器对象g用于以1/n为步长生成n x*x的值。

■ return(accumulate(fx.begin(), fx.end(), 0.0) / n);

这个数值累加和是积分f(x) = x2的近似值。

■ int main()

 {

    const int n = 10000;

    gen g(0.0, 1.0/n);

    cout << "integration program x**2" << endl;

    cout << integrate(g, n) << endl;

 }

生成器对象的初始步长为1/10 000,这意味着求值时要使用10 000个点。这个程序在我们的系统中的答案为0.333 383,而使用微积分计算得到的答案是1/3,因此数值解法可以精确到小数点后4位。

可以编写一个更精确的数值积分器。我们使用一系列矩形近似求取曲线围成的面积,其中,增量是矩形的宽,函数值是矩形的高。计算矩形高度时,增量提供了两个选择。前面的例子中使用矩形右边的点计算高度,而这个例子中为了提高积分的数值精度,分别使用矩形两边的点计算最小高度和最大高度,然后再分别使用这两个高度计算矩形的面积,最后取面积的平均值。

文件 stl_integration2.cpp

// Simple integration routine for x * x over (0, 1)

#include <iostream>

#include <numeric>

#include <algorithm>

#include <vector>

using namespace std;

// The function is represented in class gen

class gen {     // generator for integrated function

public:

   gen(double x_zero, double increment)

    : x(x_zero), incr(increment) { }

   double operator()() { x += incr; return x * x; }

private:

   double x, incr;

};

// Integrate on (0,1)

double integrate(gen g, int n, double& diff)

{

   vector<double> fx(n + 1), sm(n), lg(n);

   double s, l;

   generate(fx.begin(), fx.end(), g);

   for (int i = 0; i < n; ++i)

   if (fx[i] > fx[i + 1]) {

      sm[i] = fx[i + 1]; lg[i] = fx[i];

   }

   else {

      sm[i] = fx[i]; lg[i] = fx[i + 1];

   }

   s = accumulate(sm.begin(), sm.end(), 0.0) / n;

   l = accumulate(lg.begin(), lg.end(), 0.0) / n;

   diff = l - s;

   return (s + l) / 2;

}

int main()

{

   const int n = 10000;

   gen g(0.0, 1.0/n);

   cout << "integration program x**2" << endl;

   double d, i = integrate(g, n, d);

   cout << "integral = " << i << " +/- "

        << (d / 2) << endl;

}

第二个版本的integrate()的计算更精确,它对diff进行了误差估算。这个方法在我们的系统上运行的结果是0.333 333,可以精确到小数点后6位。

查看所有评论(0)条】

最近评论



正在载入评论列表...
热点评论