用程序来求积分的方法有很多,这篇文章主要是有关牛顿-科特斯公式。

  学过插值算法的同学最容易想到的就是用插值函数代替被积分函数来求积分,但实际上在大部分场景下这是行不通的。

  插值函数一般是一个不超过n次的多项式,如果用插值函数来求积分的话,就会引进高次多项式求积分的问题。这样会将原来的求积分问题带到另一个求积分问题:如何求n次多项式的积分,而且当次数变高时,会出现龙悲歌现象,误差反而可能会增大,并且高次的插值求积公式有可能会变得不稳定:详细原因不赘述。

  牛顿-科特斯公式解决这一问题的办法是将大的插值区间分为一堆小的插值区间,使得多项式的次数不会太高。然后通过引入参数函数

将带有幂的项的取值范围固定在一个固定范围内,这样一来就将多项式带有幂的部分的求积变为一个固定的常数,只需手工算出来即可。这个常数可以直接带入多项式求积函数。

  上式中x的求积分区间为[a, b],h = (b - a)/n, 这样一来积分区间变为[0, n],需要注意的是从这个公式可以看出一个大的区间被分为n个等长的小区间。 这一部分具体请参见任意一本有关数值计算的书!

   n是一个事先确定好的值。

  又因为一个大的插值区间需要被分为等长的多个小区间,并在这些小区间上分别进行插值和积分,因此此时的牛顿-科特斯公式被称为:复化牛顿-科特斯公式。

   并且对于n的不同取值牛顿-科特斯有不同的名称: 当n=1时,叫做复化梯形公式,复化梯形公式也就是将每一个小区间都看为一个梯形(高为h,上底为f(t), 下底为f(t+1))。这与积分的本质:无限分隔  相同。

  当n=2时,复化牛顿-科特斯公式被称为复化辛普森公式(非美国法律界著名的那个辛普森)。

  我这篇文章实现的是复化梯形公式:

    

  首先写一个函数求节点函数值求和那部分:

    

"""
@brief: 求和 ∑f(xk) : xk表示等距节点的第k个节点,不包括端点
xk = a + kh (k = 0, 1, 2, ...)
积分区间为[a, b] @param: xk 积分区间的等分点x坐标集合(不包括端点)
@param: func 求积函数
@return: 返回值为集合的和
"""
def sum_fun_xk(xk, func):
return sum([func(each) for each in xk])

  

  然后就可以写整个求积分函数了:

"""
@brief: 求func积分 : @param: a 积分区间左端点
@param: b 积分区间右端点
@param: n 积分分为n等份(复化梯形求积分要求)
@param: func 求积函数
@return: 积分值
"""
def integral(a, b, n, func):
h = (b - a)/float(n)
xk = [a + i*h for i in range(1, n)]
return h/2 * (func(a) + 2 * sum_fun_xk(xk, func) + func(b))

  相当的简单

  

  试验:

  当把大区间分为两个小区间时:

    

  分为20个小区间时:

  

  求的积分值就是这些彩色的梯形面积之和。

  测试代码:

if __name__ == "__main__":

    func = lambda x: x**2
a, b = 2, 8
n = 20
print integral(a, b, n, func) ''' 画图 '''
import matplotlib.pyplot as plt
plt.figure("play")
ax1 = plt.subplot(111)
plt.sca(ax1) tmpx = [2 + float(8-2) /50 * each for each in range(50+1)]
plt.plot(tmpx, [func(each) for each in tmpx], linestyle = '-', color='black') for rang in range(n):
tmpx = [a + float(8-2)/n * rang, a + float(8-2)/n * rang, a + float(8-2)/n * (rang+1), a + float(8-2)/n * (rang+1)]
tmpy = [0, func(tmpx[1]), func(tmpx[2]), 0]
c = ['r', 'y', 'b', 'g']
plt.fill(tmpx, tmpy, color=c[rang%4])
plt.grid(True)
plt.show()

  注意上面代码中的n并不是上文开篇提到的公式中的n,开篇提到的n是指将每一个具体的插值区间(也就是小区间)等距插n个节点,复化梯形公式的n是固定的为1.

  而代码中的n指将大区间分为n个小区间。

最新文章

  1. 如何使用Sitemap和menu创建网站导航
  2. 【GPU编解码】GPU硬编码
  3. okhttp3 get post 简单封装
  4. python 输出乱码
  5. Oracle小数点格式化
  6. LeetCode11 Container With Most Water
  7. android 小例之两列菜单关联
  8. AndroidStudio push代码到github
  9. hadoop ,传智播客目录
  10. Python 搭建环境踩过的那些坑
  11. Goland 提示 :configuration is still incorrect 的解决
  12. Spark技术内幕:Storage 模块整体架构
  13. 百度地图API实时画出动态运行轨迹(一条行驶轨迹),车头实时指向行驶方向,设置角度偏移
  14. java核心技术-(总结自杨晓峰-java核心技术36讲)
  15. mac os下不同工具go env下gopath显示不同
  16. java JDK安装教程
  17. oneinstack如何安装ssl证书和配置Let's Encrypt免费SSL证书教程汇总(转)
  18. Dao层向sql语句传递多个参数
  19. 7.代理handler
  20. Graph-BFS-图的广度优先遍历

热门文章

  1. python开发编译器
  2. 将表里的数据批量生成INSERT语句的存储过程 增强版
  3. AutoMapper
  4. [原创]mybatis中整合ehcache缓存框架的使用
  5. Android数据加密之SHA安全散列算法
  6. [原] Cgroup CPU, Blkio 测试
  7. C#日志
  8. mount报错: you must specify the filesystem type
  9. celery使用的一些小坑和技巧(非从无到有的过程)
  10. 理解JavaScript中的“this”