堆栈的大小是多少 - java -xss16M分配16兆字节或16兆字节

时间:2018-02-25 04:47:41

标签: java jvm tail-recursion factorial

我试图通过使用java -Xss160M命令限制分配给线程堆栈的大小来证明我正在使用尾递归。我正在编写一个简单的尾递归算法来寻找一个非常大的数字的阶乘:

/*
*
*my Program
*
*/

import java.math.BigInteger;

public class TailFactorial {
private BigInteger factorial(BigInteger n, BigInteger acc) {
    if (n.equals(BigInteger.ONE)) return acc;
    else return factorial(n.subtract(BigInteger.ONE), n.multiply(acc));
}
public static void main(String[] args) {
    // TODO Auto-generated method stub
    TailFactorial classs = new TailFactorial();
    int num;
    BigInteger bigNum = BigInteger.ONE;
    boolean gTG = false;
    String finalNumString = "";
    String msg = "";
    try {
        num = Integer.parseInt(args[0]);
        bigNum = BigInteger.valueOf(num);
        msg = "fact("+String.valueOf(num)+") = ";
        gTG = true;

    }catch(Exception e) {
        System.out.println("Could not get arguments, please make sure you are passing an integer");
        gTG = false;
    }
    try {
        if(gTG) {
            BigInteger finalNum = classs.factorial(bigNum ,BigInteger.ONE);
            System.out.println(String.valueOf(finalNum.bitCount()));
            finalNumString = finalNum.toString();
            //System.out.println( msg + finalNumString);
        }
        else {
            System.out.print("Exiting");
        }

    }catch(StackOverflowError e) {
        System.out.print("Not enough memory allocated to stack, try exicuting with java -Xss$bigger memory inserted here$ TrailFactorial");
    }
    catch(Exception e) {
        System.out.print("Unrecoginzed error in finding factorial");
    }



}

}

代码运行得很好,但我必须为堆栈分配50M。当我运行当前程序时,它显示结果的位数。当我发现十万的阶乘是位数为708,218时,我仍然需要使用50M。有人可以向我解释M的含义吗?它是兆字节还是位?我没有正确实现尾递归吗?

1 个答案:

答案 0 :(得分:2)

如上所述; Java不支持尾调用递归优化,因此对于较大的n值,您将始终没有堆栈。

如果你想避免这种情况,我建议你使用一个简单的循环。

public static BigInteger factorial(int n) {
    BigInteger acc = BigInteger.ONE;
    for (int i = 2; i <= n; i++)
        acc = acc.multiply(BigInteger.valueOf(i));
    return acc;
}

如果你真的,真的想要使用递归,你可以使用分而治之

public static BigInteger factorial(int n) {
    return product(1, n);
}

public static BigInteger product(int from, int to) {
    if (from == to) return BigInteger.valueOf(from);
    int mid = (from + to) >>> 1;
    return product(from, mid).multiply(product(mid + 1, to));
}

它的堆栈深度为log2(n)或最大为~32。

BTW以下代码

        System.out.println(String.valueOf(finalNum.bitCount()));
        finalNumString = finalNum.toString();
        System.out.println( msg + finalNumString);

相同
        System.out.println(finalNum.bitCount());
        System.out.println(msg + finalNum);