我很失望那些古老的数学技巧似乎正逐渐被遗忘。这里是你所要求的答案。来源于 Paul Hsieh 的优秀网站:
http://www.azillionmonkeys.com/qed/sqroot.html。请注意,你不需要关心距离;使用距离的平方就可以完成排序,速度会更快。
在二维中,我们可以使用以下公式得到一个粗略的距离度量近似值而不需要进行平方根计算:
distanceapprox(x, y) =
该公式计算结果与真实答案最多相差约8%。类似地,在三维中进行类似推导,得到如下公式:
distanceapprox (x, y, z) =
最大误差约为16%。
然而,需要指出的是,在许多情况下,距离仅用于比较。例如,在经典曼德博集合(z←z2+c)计算中,复数的大小通常与半径长度为2的边界进行比较。在这些情况下,可以通过实质上平方比较两侧(因为距离始终为非负),简单地放弃平方根。也就是说:
√(Δx2+Δy2) < d is equivalent to Δx2+Δy2 < d2, if d ≥ 0
我还应该提到,Richard G. Lyons的《理解数字信号处理》第13.2章收录了令人难以置信的二维距离算法(也称为复数幅度近似)。以下是一个例子:
Max = x > y ? x : y;
Min = x < y ? x : y;
if ( Min < 0.04142135Max )
|V| = 0.99 * Max + 0.197 * Min;
else
|V| = 0.84 * Max + 0.561 * Min
这个方法最大误差只有实际距离的1.0%。当然,代价是要进行几个分支;但即使对于此问题“被广泛接受”的答案至少也有三个分支。
如果您真的想以特定精度进行超快速的距离估计,可以通过编写自己简化的fsqrt()估计来实现,该方法使用与编译器供应商相同的基本方法,但精度较低,通过执行固定数量的迭代。例如,您可以消除极小或极大数字的特殊情况处理,并/或减少Newton-Rapheson迭代次数。这是所谓的“Quake 3”
fast inverse square root 实现的关键策略——它是具有仅一个迭代的经典Newton算法。
不要假设您的fsqrt()实现很慢,而没有进行基准测试和/或阅读源代码。大多数现代fsqrt()库实现都是无分支的并且非常快速。
例如这里是旧IBM浮点fsqrt实现。过早优化是,且始终是,万恶之源。