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

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

  下面是使用递归和尾递归分别计算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毫秒)!优化

相关文章
相关标签/搜索