Java Math.abs与Math.pow

Java Math.abs与Math.pow,java,performance,Java,Performance,所以这里有一个奇怪的问题。我正在处理kNN问题,需要找到最近的邻居。我看着远处,但再一次,我不在乎实际的距离,只是哪一个距离最近。然而,由于距离不能为负,我需要平方或取距离的绝对值 因此,有两种方法可以实现这一点: //note: it's been abstracted for multiple dimensions (not just x and y) for(int i = 0; i < (numAttributes - 1); i++) { distance += Math

所以这里有一个奇怪的问题。我正在处理kNN问题,需要找到最近的邻居。我看着远处,但再一次,我不在乎实际的距离,只是哪一个距离最近。然而,由于距离不能为负,我需要平方或取距离的绝对值

因此,有两种方法可以实现这一点:

//note: it's been abstracted for multiple dimensions (not just x and y)
for(int i = 0; i < (numAttributes - 1); i++)
{
    distance += Math.pow((a.value(i) - b.value(i)), 2);
}
//注意:它被抽象为多个维度(不仅仅是x和y)
对于(int i=0;i<(numAttributes-1);i++)
{
距离+=数学功率((a.值(i)-b.值(i)),2);
}

//注意:它被抽象为多个维度(不仅仅是x和y)
对于(int i=0;i<(numAttributes-1);i++)
{
距离+=数学绝对值(a.值(i)-b.值(i));
}

我的问题是哪个更快。由于这是一个数据挖掘应用程序,我希望它能够尽快处理信息。虽然我理解,从本质上讲,2的幂可以通过转换来实现,但我不确定在Java这样的高级语言中是否会出现这种情况,在Java中它会被转换为JVM。是否有一个原因比另一个更好?

< P>首先,考虑向量<代码> A=(0,0,0] ,<代码> B= [1,1,1] ,<代码> C=(0,0,2] < /代码>。哪一个更接近
A
?是
B
还是
C
?实际上,关心距离度量在kNN中是绝对重要的。我们只讨论曼哈顿距离和欧几里得距离。举例来说,您也可以使用余弦相似性,您应该仔细选择距离度量,并考虑到您对数据的了解

第二,代替这种低层次的优化,考虑一些更聪明的事情。例如,一旦检测到距离过大,就立即中断
for(int i=0;i<(numAttributes-1);i++)
循环

第三,使用
Math.pow(a,2)
计算
a*a
肯定是非常低效的


第四,
i<(numAttributes-1)
?你是说
i

哪个更快?你给他们两个都计时看看怎么样?或者编译这两行,看看哪一行生成了更多的指令。使用L1范数和L2范数不具有统计意义吗?什么?Math.pow(…,2)与移位无关,也不计算二的幂(这将是Math.pow(2,…)),请注意,使用这两种方法将得到不同的结果。如果你正在实现一个需要平方运算的算法,那么使用abs不仅更快,而且是错误的(尽管根据很多情况,它可能是一个足够好的近似值)。不能用一次移位计算一个正方形。可以通过移位计算2的整数幂,但这在这里没有用。2.我希望
Math.abs(d)
Math.pow(d,2)
快得多。为什么?因为
abs
应该映射到一个并清除符号位,而
pow(,2)
最好映射到乘法,最坏映射到对
pow
的实际函数调用。3.immibis是正确的:L1和L2范数具有非常不同的属性;特别是L2在任何地方都是可微的,而L1不是(0处的峰值),这在某些应用程序中会导致一系列问题。最后一个属性是非数字的,并且包含正确的答案(我想你会说),因此如果我计算,我会得到一个NAN异常。但是,看看它,我肯定应该把它从循环中删掉,并在其中加入一个break语句来缩短它。非常感谢。“使用Math.pow(a,2)来计算a*a肯定是非常低效的”。那不是真的。看@apangin哦,对了,非常有趣,没想到编译器会做这项工作:)
//note: it's been abstracted for multiple dimensions (not just x and y)
for(int i = 0; i < (numAttributes - 1); i++)
{
    distance += Math.abs(a.value(i) - b.value(i));
}