JAVA中使用递归和尾递归实现1000的阶乘

  在JAVA中求阶乘首先遇到的问题就是结果溢出,不管是使用int还是long,double都无法表示1000!这么大的天文数字,这里暂且用BigInteger解决这个问题!

  下面是使用递归和尾递归分别计算1000的阶乘:

 1 import java.math.BigInteger;
 2 
 3 public class Main {
 4 
 5     public static void main(String[] args) {
 6         long t = System.currentTimeMillis();
 7         System.out.println(factorial(new BigInteger("1000")));
 8         System.out.println(System.currentTimeMillis()- t);
 9         t = System.currentTimeMillis();
10         System.out.println(factorial2(new BigInteger("1000"),BigInteger.ONE));
11         System.out.println(System.currentTimeMillis()- t);
12     }
13 
14 
15     /**
16      * 使用线性递归计算阶乘
17      * @param n
18      * @return
19      */
20     public static BigInteger factorial(BigInteger n ){
21         if (n.compareTo(BigInteger.ZERO) < 0) return BigInteger.ZERO;
22 
23         if (n.equals(BigInteger.ONE) || n.equals(BigInteger.ZERO)) {
24             return new BigInteger("1");
25         }
26         return n.multiply(factorial(n.subtract(BigInteger.ONE)));
27     }
28 
29 
30     /**
31      * 使用尾递归计算阶乘
32      * 如果一个函数中所有递归形式的调用都出现在函数的末尾,我们称这个递归函数是尾递归的。
33      * 当递归调用是整个函数体中最后执行的语句且它的返回值不属于表达式的一部分时,这个递归调用就是尾递归。
34      * 尾递归函数的特点是在回归过程中不用做任何操作,这个特性很重要,因为大多数现代的编译器会利用这种特点自动生成优化的代码。
35      * 尾递归是极其重要的,不用尾递归,函数的堆栈耗用难以估量,需要保存很多中间函数的堆栈。
36      * 通过参数传递结果,达到不压栈的目的
37      * @param n
38      * @param result
39      * @return
40      */
41     public static BigInteger factorial2(BigInteger n,BigInteger result){
42         if (n.compareTo(BigInteger.ZERO) < 0) return BigInteger.ZERO;
43 
44         if (n.equals(BigInteger.ONE) || n.equals(BigInteger.ZERO)) {
45             return result;
46         }
47 
48         return  factorial2(n.subtract(BigInteger.ONE),n.multiply(result));
49     }
50 
51 }

输出:

402387260077093773543702433923003985719374864210714632543799910...(太长了,省略)000
38
402387260077093773543702433923003985719374864210714632543799910...(省略)000
11
Process finished with exit code 0

  从上面的代码和运行结果可以看出,尾递归使得节省了中间函数堆栈的使用,使得性能大大提高(38-11=27毫秒)!

全部评论

相关推荐

争当牛马还争不上
码农索隆:1.把简历改哈 2.猛投,狠投 3.把基础打牢 这样你在有机会的时候,才能抓住
点赞 评论 收藏
分享
醉蟀:你不干有的是人干
点赞 评论 收藏
分享
06-27 12:54
已编辑
门头沟学院 Java
累了,讲讲我的大学经历吧,目前在家待业。我是一个二本院校软件工程专业。最开始选专业是觉得计算机感兴趣,所以选择了他。本人学习计算机是从大二暑假结束开始的,也就是大三开始。当时每天学习,我个人认为Java以及是我生活的一部分了,就这样持续学习了一年半,来到了大四上学期末,大概是在12月中旬,我终于找的到了一家上海中厂的实习,但我发现实习生的工作很枯燥,公司分配的活也不多,大多时间也是自己在自学。就这样我秋招末才找到实习。时间来到了3月中旬,公司说我可以转正,但是转正工资只有7000,不过很稳定,不加班,双休,因为要回学校参加答辩了,同时当时也是心高气傲,认为可以找到更好的,所以放弃了转正机会,回学校准备论文。准备论文期间就也没有投递简历。然后时间来到了5月中旬,这时春招基本也结束了,然后我开始投递简历,期间只是约到了几家下场面试。工资也只有6-7k,到现在我不知道该怎么办了。已经没有当初学习的心劲了,好累呀,但是又不知道该干什么去。在家就是打游戏,boss简历投一投。每天日重一次。26秋招都说是针对26届的人,25怎么办。我好绝望。要不要参加考公、考研、央国企这些的。有没有大佬可以帮帮我。为什么感觉别人找工作都是顺其自然的事情,我感觉自己每一步都在艰难追赶。八股文背了又忘背了又忘,我每次都花很长时间去理解他,可是现在感觉八股、项目都忘完了。真的已经没有力气再去学习了。图片是我的简历,有没有大哥可以指正一下,或者说我应该走哪条路,有点不想在找工作了。
码客明:太累了就休息一下兄弟,人生不会完蛋的
如果实习可以转正,你会不...
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务