2011-05-14 2 views
5

BigIntegers (그냥 *,^및!)에 대한 폴란드어 표기법 계산기를 쓰고 있는데 계단식을 얻기 위해 BigInteger.ONE을 빼는 행에 OutOfMemoryError이 표시됩니다. 그 이유는 무엇입니까?OutOfMemoryError on BigInteger

package polish_calculator; 

import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.math.BigInteger; 
import java.util.Stack; 

public class Main { 
    static BigInteger factorial(BigInteger number){ 
     Stack <BigInteger> factorialStack = new Stack<BigInteger>(); 
     factorialStack.push(number); 

     while (!number.equals(BigInteger.ONE)){ //load the stack 
      factorialStack.push(number.subtract(BigInteger.ONE)); // here's the error 
     } 

     BigInteger result = BigInteger.ONE; 

     while(!factorialStack.empty()){ // empty and multiply the stack 
      result.multiply(factorialStack.pop()); 
     } 

     return result; 
    } 


    public static void main(String[] args) throws IOException { 

     BigInteger testFactorial = new BigInteger("12"); 
     System.out.println(factorial(testFactorial)); 
     Stack <String> stack = new Stack<String>(); 
     BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 
     String readExpression = br.readLine(); 
     while(!readExpression.equals("")){ 
      String [] splittedExpression = readExpression.split(" "); 
      for(int i=0; i<splittedExpression.length;i++){ 
       if(splittedExpression[i].equals("*")) 
       { 
        BigInteger operand1 = new BigInteger(stack.pop()); 
        BigInteger operand2 = new BigInteger(stack.pop()); 
        BigInteger result = operand1.multiply(operand2); 
        String stackString = result.toString(); 
        stack.push(stackString); 
       } 
       if(splittedExpression[i].equals("^")) 
       { 
        BigInteger operand1 = new BigInteger(stack.pop()); 
        BigInteger operand2 = new BigInteger(stack.pop()); 
        BigInteger result = operand1.modPow(operand2, BigInteger.ONE); 
        String stackString = result.toString(); 
        stack.push(stackString); 
       } 

       if(splittedExpression[i].equals("!")) 
       { 
        BigInteger operand1 = new BigInteger(stack.pop()); 
        BigInteger result = factorial(operand1); 

        String stackString = result.toString(); 
        stack.push(stackString); 
       } 
       else{ //it's an integer 
        stack.push(splittedExpression[i]); 
       } 
      } // end for splittedExpression.length 
     } 
    } 
} 

오류 :

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space 
     at java.math.BigInteger.subtract(BigInteger.java:1118) 
     at polish_calculator.Main.factorial(Main.java:45) 
     at polish_calculator.Main.main(Main.java:65) 
Java Result: 1 

답변

11

BigInteger.subtract 당신이 스택에 밀고 새로운 BigInteger의를 생성합니다.

그러나 원래 숫자는 여전히 동일하므로! number.equals (BigInteger.ONE) 조건은 절대로 적용되지 않습니다. 당신이

편집 (다시) 메모리가 부족할 때까지

그래서 당신은 수-1의 사본을 영원히 스택을 채우기 :도를 계산하는 매우 메모리 사용량이 방법

주 N을 계산하기 위해 스택에서 N 값을 밀어 넣어야하기 때문에 계승 (factorial)이 필요합니다. 계승이 실제로 커지기 전에 커다란 N이 필요하지는 않지만, 당신이 나아갈 때마다 곱하면 더 좋을 것입니다.

큰 계승을 효율적으로 계산하는 방법에 대한 자세한 내용은 http://en.wikipedia.org/wiki/Factorial을 참조하십시오.

+0

. number.subtract()는 실제로 number를 수정하지 않습니다. – Doug

+0

+1 매우 좋은 점. @omgzor 따라서 당신은'number = number.subtract (BigInteger.ONE);과'factorialStack.push (number);'를 사용해야합니다. – Boro