紅糖糍粑
2019-06-18 15:38:45
確定整數(shù)平方根是否為整數(shù)的最快方法我在尋找最快的方法來確定long值是一個完全平方(即它的平方根是另一個整數(shù)):我用簡單的方法,使用內(nèi)置的Math.sqrt()函數(shù),但我想知道是否有一種方法可以通過將自己限制在僅為整數(shù)的域來更快地完成它。維護查找表是不切實際的(因為大約有231.5平方小于2的整數(shù)63).下面是我現(xiàn)在所做的非常簡單和直接的方法:public final static boolean isPerfectSquare(long n){
if (n < 0)
return false;
long tst = (long)(Math.sqrt(n) + 0.5);
return tst*tst == n;}注意:我在很多場合都使用這個函數(shù)Euler項目問題。所以沒有其他人需要維護這段代碼。而這種微觀優(yōu)化實際上會產(chǎn)生影響,因為挑戰(zhàn)的一部分是在不到一分鐘的時間內(nèi)完成每一種算法,在某些問題中,這個函數(shù)需要被調(diào)用數(shù)百萬次。我嘗試了解決這個問題的不同方法:經(jīng)過詳盡的測試,我發(fā)現(xiàn)0.5對于Math.sqrt()的結(jié)果是不必要的,至少在我的機器上是不需要的。這個快速逆平方根雖然速度更快,但在n>=410881時卻給出了不正確的結(jié)果。然而,正如博比·沙夫托,我們可以在n<410881的情況下使用FISR黑客。牛頓的方法比Math.sqrt()..這可能是因為Math.sqrt()使用類似于Newton的方法,但在硬件中實現(xiàn),因此它比Java快得多。此外,牛頓的方法仍然需要使用雙倍。一種改進的牛頓方法,它使用了一些技巧,因此只涉及整數(shù)數(shù)學(xué),它需要一些黑客來避免溢出(我希望這個函數(shù)可以處理所有64位的正數(shù)帶符號整數(shù)),它仍然比Math.sqrt().二進制印章甚至更慢。這是有意義的,因為二進制CHOP平均需要16次才能找到64位數(shù)的平方根。根據(jù)約翰的測試or語句在C+中比使用switch,但在Java和C#中,or和switch.我還嘗試創(chuàng)建一個查找表(作為一個由64個布爾值組成的私有靜態(tài)數(shù)組)。然后,而不是要么切換,要么or聲明,我只想說if(lookup[(int)(n&0x3F)]) { test } else return false;..令我驚訝的是,這樣做(只是稍微)慢了一些。這是因為數(shù)組邊界在Java中被檢查.
3 回答

楊魅力
TA貢獻1811條經(jīng)驗 獲得超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
提交
取消