2维快速距离算法(Fast_Distance_2D)的解释
来源:互联网 发布:小学生编程软件下载 编辑:程序博客网 时间:2024/04/28 20:21
在平面上如果有2个点P0(x0,y0),P1(x1,y1),根据勾股定理这2点之间的距离是√((x0-x1)^2+(y0-y1)^2)。
但是sqrt()开平方根函数是费时的操作。
所以《Windows游戏编程大师技巧》中介绍了一个2维快速距离算法(Fast_Distance_2D)。
#define MIN(a, b) ((a < b) ? a : b)#define MAX(a, b) ((a > b) ? a : b)#define SWAP(a, b, t) {t = a; a = b; b = t;}int Fast_Distance_2D(int x, int y){// this function computes the distance from 0,0 to x,y with 3.5% error// fist compute the absolute value of x,yx = abs(x);y = abs(y);// compute the minimum of x,yint mn = MIN(x, y);// return the distancereturn (x + y - (mn >> 1) - (mn >> 2) + (mn >> 4));} // end Fast_Distance_2D
这个函数是求某一点(x, y)到原点(0,0)的近似距离。有大约3.5%的误差。如果要求P0(x0,y0),P1(x1,y1)之间的距离,则调用时可以写成如下形式:
dist = Fast_Distance_2D(x0 - x1, y0 - y1);
对于这个算法为什么可以这样写,作者提到了到了泰勒•麦克劳林级数展开式,即
f(x)可以表示为f(0)+f'(0)*x1/1!+f''(0)*x2/2!+...f(n)(0)*xn/n!
其中最后一项的f(n)(0)应该是指f(x)在0处的n次导数。
但是对于这是如何变成x + y - (1/2)*mn - (1/4)*mn + (1/16)*mn的原因,作者没有详细解释。
要研究这个问题,首先要把公式搞清楚。查看《高等数学》可以找到确切的描述:
泰勒(Taylor)中值定理 如果函数f(x)在含有x0的某个开区间(a, b)内具有直到(n+1)阶的导数,则当x在(a, b)内时,f(x)可以表示为(x-x0)的一个n次多项式与一个余项Rn(x)之和:
该公式称为f(x)按(x-x0)的幂展开的n阶泰勒公式。余项Rn(x)有多种形式。
在泰勒公式中,如果取x0=0,则可得到所谓的麦克劳林(Maclaurin)公式:
显然《Windows游戏编程大师技巧》第二版所写的公式实在是太粗糙了。
我们要求开平方根,那么把f(x)设为√x是不是就可以了呢?让我们试试看求它的导数。
f(x)=√x
f'(x)=(√x)'
根据导数公式(x^u)'=u·x^(u-1)
f'(x)=(x^(1/2))'=1/(2√x)
然后把0带入,发现0在分母位置。所以把f(x)设为√x无法运用麦克劳林公式。
那该怎么办呢?让我看看√x和它的导数1/(2√x)的曲线:
可以发现,如果把曲线向左偏移,则可以使0成为有效值。比如把f(x)设为√(x+1)
f(x)=√(x+1)则f'(x)=1/(2√(x+1))
我们可以继续计算得到2阶,3阶导数。所以有:
所以√(x+1)的麦克劳林公式为
为了便于理解,让我们用这个公式算一下√30。
为了运用公式,应该把它写成√(x+1)的形式:√30=√(25+5)=5*√(1+1/5)=5*(1+1/2*1/5-1/8*(1/5)^2+1/16*(1/5)^3+...)=5*(1+1/10-1/200+1/2000+...)约等于5.4775
用计算器算得5.477225575051661。看来是可以这样计算的。但其实还有另一个问题:既然要写成√(x+1)的形式,为什么不写成√(29+1)?把29带入公式,则会发现结果完全不对。
问题出在哪里?难道对于x还有其它条件的限制吗?经过再次研究才发现上面混淆了泰勒公式与泰勒级数,麦克劳林公式与麦克劳林级数的区别。《Windows游戏编程大师技巧》说的是泰勒•麦克劳林级数展开式,没有说泰勒•麦克劳林公式。
所以下面要开始讨论级数。
如果给定一个定义在区间I上的函数列u1(x),u2(x),u3(x),...,un(x),...则由这函数列构成的表达式u1(x)+u2(x)+u3(x)+...+un(x)+...
称为定义在区间I上的(函数项)无穷级数,简称(函数项)级数。
函数项级数中简单而常见的一类级数就是各项都是幂函数的函数项级数即所谓幂级数。
泰勒公式的等式右边取除余项的部分就是泰勒级数。在泰勒级数中取x0=0则为麦克劳林级数。
泰勒•麦克劳林公式只是说有这样一个等式成立。并不保证能用这个多项式的前几项之和来逼近f(x)。
所以要继续研究“函数展开成幂级数”的问题。“函数展开成幂级数”就是指,是否能找到这样一个幂级数,它在某个区间内收敛,且其和恰好就是给定的函数f(x),如果能找到这样的幂级数,我们就说,函数f(x)在该区间内能展开成幂级数,或简单地说函数f(x)能展开成幂级数,而该级数在收敛区间内就表达了函数f(x)。
有这样一个定理 设函数f(x)在点x0的某个领域U(x0)内具有各阶导数,则f(x)在该领域内能展开成泰勒级数的充分必要条件是f(x)的泰勒公式中的余项Rn(x)当n->∞时的极限为零。
所以函数展开成幂级数是有条件的。对于√(x+1)=1+(1/2)x-(1/8)x^2+(1/16)x^3+... 条件是-1<=x<=1。具体计算过程请看《高等数学》下册第十一章第四节例6。
现在我们可以回到Fast_Distance_2D。
Fast_Distance_2D其实要算的是√(x^2+y^2)。为了使用√(x+1)=1+(1/2)x-(1/8)x^2+(1/16)x^3+...就要将√(x^2+y^2)转换√(x+1)的形式。
为了对x做出区别,把√(x+1)=1+(1/2)x-(1/8)x^2+(1/16)x^3+...中的x换成z,得√(z+1)=1+(1/2)z-(1/8)z^2+(1/16)z^3+... (-1<=z<=1)
并且转换√(x^2+y^2)的形式:
然后令z=y^2/x^2,就可以带入级数展开式了。因为要满足-1<=z<=1,所以上式是假设|y|<=|x|。如果|x|<=|y|,上式就要改写成|y|√(1+x^2/y^2)。它们的形式是一样的。这就是Fast_Distance_2D中为什么要先取x,y的绝对值再取最小值的原因。
现在我们终于可以开始研究最后一行return (x + y - (mn >> 1) - (mn >> 2) + (mn >> 4));
把z=y^2/x^2带入级数展开式
但是(x + y - (mn >> 1) - (mn >> 2) + (mn >> 4))实际上是
这里是假设|y|<=|x|
这与上面的计算结果有点不一样。
所以《Windows游戏编程大师技巧》说这个算法有3.5%的误差。
- 2维快速距离算法(Fast_Distance_2D)的解释
- 一种快速求点到线段距离的算法
- 一种快速求点到线段距离的算法
- 各种距离的解释
- 各种距离的解释
- 计算两个字符串的编辑距离的快速算法
- 各种距离的详细解释
- 【图文解释】快速排序算法
- 图像快速处理算法II 距离变换
- Mahalanobis距离(马氏距离)的“哲学”解释
- Mahalanobis距离(马氏距离)的“哲学”解释
- Mahalanobis距离(马氏距离)的“哲学”解释
- MySQL性能调优 – 使用更为快速的算法进行距离计算
- 计算编辑距离的算法
- 算法之 数组的“距离”
- 编辑距离算法的实现
- 距离矢量算法的缺点
- 快速幂的简单解释
- Android学习笔记之SQLite数据库的使用及常用的增删改查方法、无sql语句的DRUD方法汇总
- 最近网上的一个热门话题引起的。。
- the difference between kernel stack and user stack
- 中国大学MOOC-翁恺-C语言程序习题第六周
- web server
- 2维快速距离算法(Fast_Distance_2D)的解释
- 顶级风投First Round Capital对创业者的30个建议
- json学习总结
- EJB3中JTA和RESOURCE_LOCAL的区别
- winform下利用chart显示ADC数据
- “像元分组” 算法:将二值图像中处于相邻的元素进行分组标号, 使得属于同一个分组的像元集合,其编号都相同
- 源自Google、Facebook、Netflix和Cisco的10款开源安全工具很值得回味
- 项目知识储备-自动属性 隐式类型Var
- c++编译器会为类添加那些成员函数