2011-05-14 52 views
5

我正在为BigIntegers(只是*,^和!)编写一个波兰记法计算器,我得到一个OutOfMemoryError上线,我减去BigInteger.ONE以获得阶乘的工作原因?BigInteger上的OutOfMemoryError

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!当你走的时候将它们相乘会更好,虽然当然在阶乘变得非常大之前你不需要大的N。

请参阅http://en.wikipedia.org/wiki/Factorial了解有关高效计算大型因子的一些详细信息。

+0

这个。 number.subtract()实际上并不修改数字。 – Doug 2011-05-14 16:49:32

+0

+1非常好的一点。 @omgzor因此你必须使用'number = number.subtract(BigInteger.ONE);'然后'factorialStack.push(number);' – Boro 2011-05-14 16:50:20