心血来潮,写了个N阶乘小程序,在大于10000的时候,抛出了java.lang.StackOverflowError错误.估计是递归嵌套太多所造成的.后来上网搜索了一下,发现果然是这个原因.
为了简化这个问题描述,另外写了段非常简单测试.public class T { int max;
T(int i){
max = i;
}
void Recursive(int i){
if(i > 0)
Recursive(--i);
else
return; }
public static void main(String[] args){
T t= new T(100000);//10000没有问题,加上个0就有问题了
t.Recursive(t.max);
}
}我想请问各位,有没有办法能够加深STACK的长度.
(java -Xss128m T 我已经试过了,似乎没有作用,bea的解释是java栈有两种,java 和c的.这个参数只能对c的栈起作用).我想,之所以用递归,就是因为大家不知道程序执行的深度是多少.那怎么样解决递归所带来的这个运行错误呢?如果实在有必要转换成非递归方法,请各位高手为小弟指条N阶乘的算法思想吧.

解决方案 »

  1.   

    void Recursive(int i){
        for(;i>0;i--){
    ...;        
        }
        }
    for循环就行了,递归不是你那么用的。
      

  2.   

    malligator:-Xss 说是可以设定每个线程stack的深度,不过感觉没用。(申请多了,系统会告急的,嘿嘿)zzyhuian06142:大哥,别瞎起哄,这个怎么不是递归了?
    zhuyf333:谢谢你提示for循环,我只是觉得好像没有看懂我的问题,我的意思是在必须递归解决问题的时候,如何控制其不让JVM崩掉。所以我举出的只是一个模型。要求:精确测出10000左右的N阶乘(再大了咱们先不提)
    我的N阶乘思路:
    1)双向环形链表2)每个节点存贮一段数据(选取的是max=99999,想想原因?)3)节点乘以n,有进位,则进位与下一位相加,(有必要递归进位相加);若到头,新建节点4)遍历链表,依次输出到txt文本(注意不足6位要补0)。问题就出在递归,在9000左右还能正常且较快速执行,10000就StackOverflowError了。汗~~~
    我只是想问清楚有没有办法扩大JVM对stack的限制。
      

  3.   

    如果递归深度是不确定并且无最大值,而且你又非用递归不可,又不让 JVM 崩掉,那是不可能的。就算JVM没有限制,OS 也有限制。
    就算OS 没有限制,RAM也有极限。
    就算你用的虚拟内存,那硬盘空间也有限制。所以,像你这种问题是不可能解决的。
      

  4.   

    呵呵,我当然知道这个问题了。所以我限定了10000,且用的int存贮,我不是为了完成一项不可能的任务,而是在力所能及的范围内解决一点小问题。能否让JVM稍微放宽点限制而已?感谢各位的回答先。还是自己思考算了。呵呵
      

  5.   

    解决不了
    确实有你说的问题  
    csdn上 不是星星的回答基本上不用看 
    XX太多了
      

  6.   

    insiku(不问世事好多年~~|| PM我时请附上帖子地址) ( 你牛B?
    好像你头上也没顶颗星星吧。
      

  7.   

    哎,又是一个专牛角尖的,以前我就是因为用递归的问题去问高手,结果被教训了一通:一看用递归的就是学生一类,实际中谁敢用递归,递归这东西拿教学还行。还是用迭代法好。还有楼主的程序求不了阶乘的。int factoriell(int n) {
    if (n < 0) {
    return -1;
    }
    if (n == 0 || n == 1) {
    return 1;
    }return n * factoriell(n -1);
    }如果你真要求1000的阶乘的话,用原始类型,那么c, c++, java都帮不了你,必须得用数组来存储计算结果才行。这个东西讲起来就有些麻烦了,可以到网上搜索一下怎么处理计算大数的程序,应该就知道办法了。或者好像ruby的数字处理不限大小,大可直到内存存不下,也许你真要这样做,可以试一下。
      

  8.   

    jorneyR(胡言乱语不怕死的菜鸟):感觉你还真是“胡言乱语不怕死的菜鸟”,首先我不是要你教我N阶乘怎么写。你说必须用数组存储,那是你个人的理解,我就不发表批驳的言辞了。其次,你的N阶乘能算过100我就信你的邪了。别没吃饱乱嚷嚷好不好,看清楚,我上面的只是举例说明java递归的问题,并不是N阶乘程序。
      

  9.   

    兄弟 递归不是用来玩的。
    强烈反对用递归来做阶乘问题和神奇数字(斐波那契数列)问题的。有循环放着不用,用这个简直是在糟蹋程序,并且糟蹋硬件。不管在任何地方,任何语言,递归都是尽量避免使用的。虽然没有goto那么明确,但是肯定是说过,尽量避免使用。更没有你这么用的。
    不过这样也告诉我们一个教训:使用递归的时候,一定要记得检测内存,及时抛出异常,否则程序中止丢失数据了,可是影响了程序的健壮性的。
      

  10.   

    汗,大家别争论了,楼主是用在说JVM的栈的容量问题。不是N的阶乘。不是递归。大家有什么好的办法扩展JVM的栈吗?
      

  11.   

    cuilichen(fjfjfjfj) :兄弟,还是你明白我的苦衷啊~~~!!!!呵呵。感觉有些同志没太看懂我说的重点啊。iceofire():
    恩,好的,谢谢你的忠告。的确,我感觉也是,在递归面前就是脆弱的羔羊。不知道什么时候就会被搞死。我正在改写我那段程序,使其在可预计和控制的有限次递归或循环中结束。
      

  12.   

    但是有点不甘心的还是那个问题,JVM就不能设置一下,放宽点stack限度么.
      

  13.   

    有点感想想和大家分享:1)上面忘了说了,最开始用int存储,我选择max=99999,也就是说,超过100000就往前进位.(之所以没用999,是考虑到可能造成的频繁进位影响效率;也没有取得过大,如100000000,否则能够到达的阶乘n的上限也就被限制在21,也就失去意义了;如果采用"计算时用long,结果转成int"的做法,虽说可以使得n和节点值都变得较大,但我放弃这么做,可能是我对强制转型的"惧怕"吧)总之,long足够大,我先用着再说,以后慢慢计较也不迟:P,后来我把int改成long,原本以为了扩大每个节点的最大容纳信息量,来使递归(主要发生在有进位的时候)的次数减少,似乎并没有起到作用.但是改成long以后(节点max=999999999),却方便突破Integer.MAX_VALUE / 100000 = 21474的限制,也就是说可以算到21474以上,于是试了一下,嘿嘿50000也过去了,爽.2)关于结果的测试,可以把结果打到txt中.或者直接在控制台把结果粘贴到word中,用微软的计算器算出结果进行比对.其一看前面的几十位是否一样,其二用"字符统计"查看总的数位,看和计算器的结果是否一样.(我就是这样发现最开始节点没有补足数位的问题的)