Answers:
使用平方长度比较距离时,我没有发现任何缺点。这样思考:您只是跳过了sqrt
,不会给您带来任何额外的准确性。如果您不需要实际的欧几里德距离,则可以放心sqrt
。
当然,平方长度的比例尺与欧几里得距离完全不同,因此对于诸如寻路启发式算法之类的东西而言,它是不好的选择。
d^2
表现糟糕的文章。在A *中|dx| + |dy|
效果很好。我一个月前读后没有链接。
我能想到的唯一缺点是在处理大数时,平方会溢出。
例如,在Java中:
int x = Integer.MAX_VALUE / 1000000; //2147
int y = Integer.MAX_VALUE / 5000; //429496
System.out.println("x < y: " + (x < y)); //true
System.out.println("x*x: " + (x * x)); //4609609
System.out.println("y*y: " + (y * y)); //-216779712 - overflows!
System.out.println("x*x < y*y: " + (x * x < y * y)); //false - incorrect result due to overflow!
同样值得注意的是,当您使用Math.pow()使用完全相同的数字并从从以下方法返回的double中将其转换回int 时会发生什么Math.pow()
:
System.out.println("x^2: " + (int) (Math.pow(x, 2))); //4609609
System.out.println("y^2: " + (int) (Math.pow(y, 2))); //2147483647 - double to int conversion clamps to Integer.MAX_VALUE
System.out.println("x^2 < y^2: " + ((int) (Math.pow(x, 2)) < (int) (Math.pow(y, 2)))); //true - but for the wrong reason!
工作正常吗?不,它只给出了正确的答案,因为y*y
被钳制了Integer.MAX_VALUE
,x*x
小于Integer.MAX_VALUE
。如果x*x
也受到限制,Integer.MAX_VALUE
那么您将得到错误的答案。
类似的原理也适用于浮点数和双精度数(除非它们显然在溢出之前具有更大的范围)以及任何其他允许静默溢出的语言。
float
s作为坐标,只有在大约10^38
不之后才溢出int
。
如果编写的算法要求您计算最佳位置,则可能会遇到麻烦。例如,假设您有一组对象,并且您试图计算到所有对象的总距离最小的位置。仅举一个具体的例子,假设我们正在尝试为三座建筑物供电,并且我们想弄清楚发电厂的去向,以便我们可以使用最小的电线总长将其连接到所有建筑物。使用距离平方度量,您将最终得出电厂的x坐标为所有建筑物的x坐标的平均值(类似地,为y坐标)。使用普通距离度量,解决方案将有所不同,并且通常与距离平方解决方案相距甚远。
x^2
与之相比,使用起来更容易|x|
。
使用距离平方几乎总是很好并且对性能有好处。以下注意事项很重要:
如果要考虑多个距离的总和,则距离平方将不准确。例如,我有两个距离,我想确保它们的总和小于10。以下代码不正确:
a = get_distance_squared(c,d);
b = get_distance_squared(e,f);
assert(a+b < 10^2);
在以下无效情况下,它无法断言:a=36
和b=49
。在这种情况下,第一个长度是6,第二个长度是7;它们的总和大于10,但平方和不是100或更大。
另一个考虑因素:对于实值距离,距离平方将始终为正。例如,如果要测量位移,则可能需要处理负值,而对它们进行平方将不会。