2012-05-18 76 views
-1

我有這種奇怪的錯誤。StackoverflowError

我試圖使用BigInteger類實現基本的歐幾里得算法,如圖所示。當我運行它,它會拋出StackoverFlowError,而如果我調試它,它會正確運行,並給我正確的答案。

我認真不理解調試和正常運行期間的差異。

 static BigInteger gcd(BigInteger a, BigInteger b) { 
     if (a.equals(BigInteger.ZERO)) { 
      return b; 
     } else if (b.equals(BigInteger.ZERO)) { 
      return a; 
     } 
     BigInteger max = a.max(b); 
     BigInteger min = a.min(b); 
     return gcd(max.subtract(min), min); 
     } 
+0

差異可能是堆棧大小 - 嘗試http://stackoverflow.com/questions/2127217/java-stack-overflow-error-how-to-increase-the-stack-size-in-eclipse或http:/ /stackoverflow.com/questions/3700459/how-to-increase-to-java-stack-size – maialithar

+1

哪些輸入失敗? – NPE

+1

你最初的投入是什麼? –

回答

0

這不是GCD的歐幾里得算法。正確的GCD算法可以很容易地表示爲遞歸過程,因爲迭代次數實際上很小。但是,這種錯誤實施的算法可以運行數百萬次迭代,例如如果'a'是1,000,000,'b'是1,這會導致100萬次遞歸調用。 (但是,這個調用是一個尾遞歸調用,所以一個好的Java實現實際上會優化掉堆棧幀。但是,這似乎並沒有發生,儘管調試器版本可能會實現尾部調用優化,但這聽起來很奇怪。)

在實際算法中,遞歸步驟是(a%b,b)而不是(a - b,b)。谷歌爲「euclid GCD算法」。

+0

謝謝,實際上讀取它並使用模數運算來實現。 – maress

0

如果用mod操作替換重複的減法,該算法將需要更少的調用。檢查如果max非常大並且min非常小,會發生什麼情況。

+0

使用mod操作時不會拋出錯誤。爲什麼它會在減法上拋出錯誤?即使內置類型爲long,也會引發錯誤 – maress

+0

如果輸入很長,那麼最差的情況是每次從Long.MAX_VALUE減1,總共需要Long.MAX_VALUE堆棧幀。這將最終溢出任何合理大小的堆棧。 – fgb

+0

所以我想,遞歸是不是最好的東西在這裏使用?在調試過程中,我發現這些值之間的實際區別確實導致了一個stackoverflow,即使最大值遠遠小於Long.MAX_VALUE。然而,stackoverflow的原因是適當的,但另一個有趣的問題是,爲什麼調試時沒有stackoverflow?調試,貫穿至完成? – maress