在工程实践过程中,有时候是离不开数值计算的。
有时专门针对手头问题编写一个数值函数用来代替库函数,可能会提高程序的运行速度。
本章从一个计算三围空间中点之间的距离开始(数据挖掘中十分常见)
程序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版的。