• 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毫秒)!

  • 相关阅读:
    UVA 1660 Cable TV Network
    UVA 1149 Bin Packing
    UVA 1610 Party Games
    UVA 12545 Bits Equalizer
    UVA 11491 Erasing and Winning
    UVA 1611 Crane
    DataTable循环删除行
    SqlBulkCopy使用心得 (大量数据导入)
    JQuery选择器大全
    java学习--GUI3
  • 原文地址:https://www.cnblogs.com/hyyq/p/11308739.html
Copyright © 2020-2023  润新知