BigInteger 上的 OutOfMemoryError

发布于 2024-11-07 02:18:15 字数 3072 浏览 0 评论 0原文

我正在为 BigIntegers 编写一个波兰表示法计算器(仅 *、^ 和!),并且在减去 BigInteger.ONE 的行上收到 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

I'm writing a polish notation calculator for BigIntegers (just *, ^ and !) and I'm getting an OutOfMemoryError on the line where I'm subtracting BigInteger.ONE to get the factorial to work, why?

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
        }
    }
}

Error:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

墨落成白 2024-11-14 02:18:15

BigInteger.subtract 生成一个新的 BigInteger,您将其推入堆栈。

但原始数字仍然相同,因此条件 !number.equals(BigInteger.ONE) 永远不会为真。

因此,您将永远用 number-1 的副本填充堆栈,直到内存耗尽

编辑(再次):

请注意,这也是一种非常消耗内存的计算阶乘的方法,因为您需要推送堆栈上的N个值要计算N!将它们相乘会更好,当然,在阶乘变得非常大之前,您不需要很大的 N。

有关有效计算大阶乘的一些详细信息,请参阅 http://en.wikipedia.org/wiki/Factorial

BigInteger.subtract generates a new BigInteger, which you are pushing onto the stack.

But the original number is still the same, so the condition !number.equals(BigInteger.ONE) will never be true.

So you fill the stack forever with copies of number-1 until you run out of memory

Edited (again):

Note that is also a very memory-hungry way of calculating the factorial, since you need to push N values on the stack to calculate N! Multiplying them as you go along would be better, although of course you don't need a large N before the factorial becomes very large indeed.

See http://en.wikipedia.org/wiki/Factorial for some details on calculating large factorials efficiently.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文