2012-05-18 5 views
-1

J'ai ce genre d'erreur bizarre. J'essaye d'implémenter l'algorithme euclidien de base en utilisant la classe BigInteger comme montré. Quand je l'exécute, il lance StackoverFlowError, alors que si je le débogue, il fonctionne correctement et me donne la bonne réponse.StackoverflowError

Je ne comprends pas sérieusement la différence lors du débogage et de l'exécution normale.

 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

La différence est probablement dans la taille de la pile - essayez http://stackoverflow.com/questions/2127217/java-stack-overflow-error-how-to-increase-the-stack-size-in-eclipse ou http://stackoverflow.com/questions/3700459/how-to-increase-to-java-stack-size – maialithar

+1

Sur quelles entrées échoue-t-il? – NPE

+1

Quelles sont vos entrées de départ? –

Répondre

0

Ce n'est pas l'algorithme euclidien pour GCD. L'algorithme GCD correct peut être facilement défini comme une procédure récursive parce que le nombre d'itérations est en pratique petit. Mais cet algorithme implémenté incorrectement peut fonctionner pour des millions d'itérations, par ex. si 'a' est 1 000 000 et 'b' est 1, ce qui donne 1 million d'appels récursifs. (Cependant, l'appel est un appel récursif de queue, donc une bonne implémentation Java permettrait d'optimiser le cadre de la pile.) Cependant, pour une raison inconnue, la version du débogueur pourrait implémenter l'optimisation des appels. , bien que cela semble étrange.)

Dans l'algorithme actuel, l'étape récursive est (a% b, b) au lieu de (a - b, b). Google pour "algorithme GCD euclid".

+0

Merci, lisez-le réellement et mis en œuvre en utilisant l'opération de module. – maress

0

L'algorithme nécessiterait moins d'appels si vous avez remplacé la soustraction répétée par une opération mod. Vérifiez ce qui se passe si max est très grand et min est très petit.

+0

L'utilisation de l'opération mod fonctionne sans lancer l'erreur. Pourquoi lance-t-il l'erreur sur la soustraction? Même pour un type intégré long, il renvoie l'erreur – maress

+0

Si l'entrée est longue, alors le pire des cas serait de soustraire 1 à Long.MAX_VALUE à chaque fois, ce qui nécessite un total de cadres de pile Long.MAX_VALUE. Cela finirait par déborder la pile pour toute taille raisonnable. – fgb

+0

Donc, je suppose, la récursivité n'est pas la meilleure chose à utiliser ici? Au cours du débogage, j'ai remarqué qu'une différence substantielle entre les valeurs entraîne un stackoverflow, même si la valeur max est nettement inférieure à Long.MAX_VALUE. Cependant, la raison de stackoverflow est appropriée, mais l'autre question fondamentale est: pourquoi n'y a-t-il pas de stackoverflow lors du débogage? Le débogage, se termine à la fin? – maress