基于泰勒(Taylor)中值定理的低开销快速距离算法(Fast_Distance_2D)

在一般计算点和点的距离的时候,一般会利用平方根公式写成这样:

double dist(TwoCoor &o1,TwoCoor &o2)
{
    return sqrt((pow((o1.getX() - o2.getX()),2)+pow((o1.getY() - o2.getY()),2)));
}

最近看《3D游戏编程大师技巧(上篇)》的时候提到了一个重要的算法Fast_Distance_2D,旨在用低开销的方法去计算点和点的距离,这个算法在André LaMothe的代表作《Windows游戏编程大师技巧 (第2版)》中有着更详细的介绍,不过这种算法存在着不小的误差(2D版本的最大误差为3.5%,3D版本约为8%)

这种算法的计算过程极为简洁,书中计算的是(0,0)点到任意一点的距离:


#define MIN(a, b) ((a < b) ? a : b)
 
#define MAX(a, b) ((a > b) ? a : b)
 
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,y
x = abs(x);
y = abs(y);
 
// compute the minimum of x,y
int mn = MIN(x, y);
 
// return the distance
return (x + y - (mn >> 1) - (mn >> 2) + (mn >> 4));
 
} // end Fast_Distance_2D

主要用到了泰勒/麦克劳林方程 

想要计算任何两点的距离,改成(x1-x2,y1-y2)到(0,0)点的距离就可以了

在计算机中计算平方根是个极其费时的消耗,在x86的CPU中使用FSQRT指令实现浮点数的开平方,是利用牛顿迭代法去实现的,迭代计算求解的方式开销不小,如果FMUL(CPU的乘法指令) 大约需要 1-3 个周期,而 FSQRT(CPU求根指令) 大约需要 70 个周期,这种开销是非常大

计算机中计算乘法和平方,但是要对它们进行逆运算,除法或者开方,就需要不断迭代,能不用就尽量不用)

尤其注意能不用平方根就尽量不用平方根:

如果一个圆的半径为r,圆心为(x1,x2),需要有个点要计算在不在圆内,坐标为(y1,y2)

完全可以用(x1-x2)的和(y1-y2)的平方和r的平方比较,而避免了开方操作,这就直接避免了开根计算

你可能感兴趣的:(算法,数学建模,c++)