确定整数平方根是否为整数的最快方法我在寻找最快的方法来确定long值是一个完全平方(即它的平方根是另一个整数):我用简单的方法,使用内置的Math.sqrt()函数,但我想知道是否有一种方法可以通过将自己限制在仅为整数的域来更快地完成它。维护查找表是不切实际的(因为大约有231.5平方小于2的整数63).下面是我现在所做的非常简单和直接的方法:public final static boolean isPerfectSquare(long n){
if (n < 0)
return false;
long tst = (long)(Math.sqrt(n) + 0.5);
return tst*tst == n;}注意:我在很多场合都使用这个函数Euler项目问题。所以没有其他人需要维护这段代码。而这种微观优化实际上会产生影响,因为挑战的一部分是在不到一分钟的时间内完成每一种算法,在某些问题中,这个函数需要被调用数百万次。我尝试了解决这个问题的不同方法:经过详尽的测试,我发现0.5对于Math.sqrt()的结果是不必要的,至少在我的机器上是不需要的。这个快速逆平方根虽然速度更快,但在n>=410881时却给出了不正确的结果。然而,正如博比·沙夫托,我们可以在n<410881的情况下使用FISR黑客。牛顿的方法比Math.sqrt()..这可能是因为Math.sqrt()使用类似于Newton的方法,但在硬件中实现,因此它比Java快得多。此外,牛顿的方法仍然需要使用双倍。一种改进的牛顿方法,它使用了一些技巧,因此只涉及整数数学,它需要一些黑客来避免溢出(我希望这个函数可以处理所有64位的正数带符号整数),它仍然比Math.sqrt().二进制印章甚至更慢。这是有意义的,因为二进制CHOP平均需要16次才能找到64位数的平方根。根据约翰的测试or语句在C+中比使用switch,但在Java和C#中,or和switch.我还尝试创建一个查找表(作为一个由64个布尔值组成的私有静态数组)。然后,而不是要么切换,要么or声明,我只想说if(lookup[(int)(n&0x3F)]) { test } else return false;..令我惊讶的是,这样做(只是稍微)慢了一些。这是因为数组边界在Java中被检查.
3 回答
杨魅力
TA贡献1811条经验 获得超6个赞
public final static boolean isPerfectSquare(long n){ if (n < 0) return false; switch((int)(n & 0xF)) { case 0: case 1: case 4: case 9: long tst = (long)Math.sqrt(n); return tst*tst == n; default: return false; }}
int isPerfectSquare(int n){ int h = n & 0xF; // h is the last hex "digit" if (h > 9) return 0; // Use lazy evaluation to jump out of the if statement as soon as possible if (h != 2 && h != 3 && h != 5 && h != 6 && h != 7 && h != 8) { int t = (int) floor( sqrt((double) n) + 0.5 ); return t*t == n; } return 0;}
添加回答
举报
0/150
提交
取消