编程珠玑2第14章 编写数值计算程序

在工程实践过程中,有时候是离不开数值计算的。

有时专门针对手头问题编写一个数值函数用来代替库函数,可能会提高程序的运行速度。

本章从一个计算三围空间中点之间的距离开始(数据挖掘中十分常见)

程序1计算了用向量A[1..K]和B[1..K]表示的点之间的距离。

1 Sum:=0.0
2 for J:=1 to K do
3 T:=A[J]-B[J]
4 Sum:=Sum+T*T
5 return sqrt(Sum)

程序1的优点是简单,容易理解。但它也有一些缺点:

1.即使输入中间的计算的都在有效范围,它也可能产生溢出。

2.程序开销比较大

我们的目标是提供更快速的用于计算距离的程序。

如果我们只需要对距离的大小进行比较,那么由sqrt的单调性可以知道它是多余的。

但是这里我们不能使用这个方法。

给出牛顿迭代法。牛顿迭代法是一种比较常见的求解方法,我这个就不细讲了。

为了计算 根号a,由牛顿迭代法可知此处的迭代方程为x=(x+a/x)/2。

下面给出一个牛顿迭代程序2

 1 T:=abs(A[1]-B[1])
2 Max:=T;Sum:=T*T
3 for J:=2 to K do
4 T:=abs(A[J]-B[J])
5 if T>Max then Max:=T
6 Sum:=Sum+T*T
7 if Sum=0.0 then return 0.0
8 /*find sqrt(Sum), starting at Max*/
9 Eps=1.0e-7
10 Z:=Max
11 loop
12 NewZ:=0.5*(Z+Sum/Z)
13 if abs(NewZ-Z)<=Eps*NewZ then break
14 Z:=NewZ
15 return NewZ

当K=2的时候,程序2比程序1快大约56%。但是当K=16时,程序2只比程序1快大约1.5%。

此时瓶颈不是平方根,循环以及收敛测试抵消了大部分省出的时间。

改进方法就是选取一个较好的迭代初始值并固迭代次数。

假设K<=a2,设D是最大差,那么距离至多为aD。所以所求的值在区间[D,aD]内。

于是我们可以令初始x为D和aD的几何平均值,即 D*√a。

当a=4时,x=2D。且作者通过脚手架发现将程序2中的循环展开四次就可以计算出精确结果了。

需要指出的是,一个快速的距离程序的过程受到很多因素的影响。

例如,本章的工作对于一个具有硬件平方根指令的系统可能适得其反。

对于较大的K值,平方根的开销就显得次要了。

--------------------------------------------------------------------------------------

编程珠玑II到这里就全部结束了,悲剧的是昨天有个同学跟我说。

我看的编程珠玑II不是编程珠玑第2版,有机会的话在整个第2版的。
 

原文地址:https://www.cnblogs.com/2010Freeze/p/2371648.html