将矢量缩放到所需长度的最佳方法

时间:2013-09-23 18:01:21

标签: c++ floating-point geometry computational-geometry

问题是关于这个相当基本的操作的最强大和最快的实现:

给定向量(X,Y)计算给定长度desiredLength的共线向量。至少有两种方法:

一。找到(X,Y)的长度并相应地重新缩放:

double currentLength = sqrt(X*X + Y*Y);
if(currentLength == 0) { /* Aye, Caramba! */ }
double factor = desiredLength / currentLength;
X *= factor;
Y *= factor;

两个。找到(X,Y)的方向并在该方向上形成desiredLength的向量:

if(X == 0 && Y == 0) { /* Aye, Caramba! */ }
double angle = atan2(Y, X);
X = desiredLength * cos(angle);
Y = desiredLength * sin(angle);

哪种方法更适合开发强大的应用程序,更好的数值稳定性,更快的执行等?

3 个答案:

答案 0 :(得分:2)

没有一个正确的答案,因为它将取决于实施。 但是:对任何合理的现代实施,四个基本 操作和sqrt将精确到最后一位二进制数字。从一个 从实施质量来看,人们希望也一样 对math.h中的所有函数都是如此,但它更少 某些。在具有IEEE算法的机器上(Windows和主流 Unix平台),将实现四个操作 sqrt 硬件,其中三角运算通常需要一个 软件实现,通常需要数十个基本操作。 虽然一些浮点处理器确实直接支持它们,但是 至少在有限的范围内,即使这样,它们通常也会慢一些 比四个基本操作。

所有这些都支持你的第一次实施,至少是 关于速度(可能与数值稳定性有关) 孔)。

答案 1 :(得分:1)

我希望方法一更好至少在性能方面,因为sqrt + 2乘法应该比3个trig操作便宜。 我猜它在其他方面也更好(或者更糟),因为它涉及一个近似值(sqrt)而不是2(每个轴)。 sqrt近似也由x和y“共享”。

答案 2 :(得分:1)

最好使用hypot(x,y)而不是sqrt(x*x+y*y),因为可推理的hypot实现可以帮助您避免下溢/溢出情况。

示例:hypot(1.0e300,1.0e300)hypot(1.0e-300,1.0e-300)

然后评估x / hypot(x,y)是安全的,即使在逐渐下溢(非规范化数字)的情况下,例如x = 1.0e-320,y = 0,同时评估desiredLength / hypot(x,y)可能很好溢出。

所以我会写

double h  = hypot(x,y);
double xd = desiredLength*(x/h);
double yd = desiredLength*(y/h);

如果x,y都为零,你会得到一些除零异常和nan结果,所以不要在if中处理它。