JAVA中使用递归和尾递归实现1000的阶乘的比较
在JAVA中求阶乘首先遇到的问题就是结果溢出,不管是使用int还是long,double都无法表示1000!这么大的天文数字,这里暂且用BigInteger解决这个问题!
下面是使用递归和尾递归分别计算1000的阶乘:
import java.math.BigInteger;
public class Main {
public static void main(String[] args) {
long t = System.currentTimeMillis();
System.out.println(factorial(new BigInteger("1000")));
System.out.println(System.currentTimeMillis()- t);
t = System.currentTimeMillis();
System.out.println(factorial2(new BigInteger("1000"),BigInteger.ONE));
System.out.println(System.currentTimeMillis()- t);
}
/**
* 使用线性递归计算阶乘
* @param n
* @return
*/
public static BigInteger factorial(BigInteger n ){
if (n.compareTo(BigInteger.ZERO) < 0) return BigInteger.ZERO;
if (n.equals(BigInteger.ONE) || n.equals(BigInteger.ZERO)) {
return new BigInteger("1");
}
return n.multiply(factorial(n.subtract(BigInteger.ONE)));
}
/**
* 使用尾递归计算阶乘
* 如果一个函数中所有递归形式的调用都出现在函数的末尾,我们称这个递归函数是尾递归的。
* 当递归调用是整个函数体中最后执行的语句且它的返回值不属于表达式的一部分时,这个递归调用就是尾递归。
* 尾递归函数的特点是在回归过程中不用做任何操作,这个特性很重要,因为大多数现代的编译器会利用这种特点自动生成优化的代码。
* 尾递归是极其重要的,不用尾递归,函数的堆栈耗用难以估量,需要保存很多中间函数的堆栈。
* 通过参数传递结果,达到不压栈的目的
* @param n
* @param result
* @return
*/
public static BigInteger factorial2(BigInteger n,BigInteger result){
if (n.compareTo(BigInteger.ZERO) < 0) return BigInteger.ZERO;
if (n.equals(BigInteger.ONE) || n.equals(BigInteger.ZERO)) {
return result;
}
return factorial2(n.subtract(BigInteger.ONE),n.multiply(result));
}
}
输出:
402387260077093773543702433923003985719374864210714632543799910...(太长了,省略)000
38
402387260077093773543702433923003985719374864210714632543799910...(省略)000
11
Process finished with exit code 0
从上面的代码和运行结果可以看出,尾递归使得节省了中间函数堆栈的使用,使得性能大大提高(38-11=27毫秒)!
JAVA中使用递归和尾递归实现1000的阶乘的比较的更多相关文章
- Java中的递归运算
Java中的递归运算是一种在自己的方法内部调用自己的方法 递归的设计思想是:把一个复杂的问题,分解为若干个等同的子问题,重复执行,直到之问题能够简单到直接求解,这样复杂的问题就得以解决. 递归运算有两 ...
- 【笔试题】Java 中如何递归显示一个目录下面的所有目录和文件?
笔试题 Java 中如何递归显示一个目录下面的所有目录和文件? import java.io.File; public class Test { private static void showDir ...
- 2018.3.31 java中的递归
java中的递归 1.概念 定义一个方法时,出现本方法调用本方法的过程,称之为递归 2.特点 必然有一个边界条件 使用递归代码往往更简洁,可读性强 3.什么时候使用递归 n的阶乘和n的累加定义 f(n ...
- Java中的递归调用
Java中不合理的使用递归调用,可能会导致栈内存溢出,这点是需要注意的. java将为每个线程维护一个栈,栈里将为每个方法保存一个栈帧,栈帧代表了一个方法的运行状态. 也就是我们常说的方法栈.最后一个 ...
- AJPFX:不用递归巧妙求出1000的阶乘所有零和尾部零的个数
package com.jonkey.test; import java.math.BigInteger; public class Test6 { /*** @param args* 需求:求出1 ...
- Java中的递归原理分析
解释:程序调用自身的编程技巧叫做递归. 程序调用自身的编程技巧称为递归( recursion).递归做为一种算法在程序设计语言中广泛应用. 一个过程或函数在其定义或说明中有直接或间接调用 ...
- java基础06 Java中的递归
一.递归是指直接或间接地调用自身. 二.递归的注意事项: A:要有出口,否则就是死递归 B:次数不能过多,否则内存溢出 C:构造方法不能递归使用 三.举例子 递归 ...
- Java 中的递归
递归 递归 一种通过调用某个方法来描述需要重复进行的操作.该方法的特点就是可以自己调用自己. 案例一 排队的问题 在生活中,我们经常需要排队.在排队中,我们怎么才能知道自己所排在第几位呢? 我们也许会 ...
- Java中通过递归调用删除文件夹下所有文件
摘自 : http://blog.sina.com.cn/s/blog_79333b2c0100xiu4.html import java.io.File; public class FileTest ...
随机推荐
- ABAP函数篇2 测试DATE_CONVERT_TO_FACTORYDATE
DATE_CONVERT_TO_FACTORYDATE 根据日期返回工厂日历日期 函数功能说明: 标出工作日的计算方法 输入传输 CORRECT_OPTION = '+'如果指定的日期不是工作日, ...
- Python - Django - 页面上展示固定的页码数
如果页数太多的话,全部显示在页面上就会显得很冗杂 可以在页面中显示规定的页码数 例如: book_list.html: <!DOCTYPE html> <html lang=&quo ...
- 【计算机视觉】图像配准(Image Registration)
(Source:https://blog.sicara.com/image-registration-sift-deep-learning-3c794d794b7a) 图像配准方法概述 图像配准广泛 ...
- 迅速生成项目-react-scripts
推荐指数:
- 03点睛Spring MVC 4.1-REST
转发:https://www.iteye.com/blog/wiselyman-2214290 3.1 REST REST:Representational State Transfer; REST是 ...
- golang 学习 (八)协程
一: 进程.线程 和 协程 之间概念的区别: 对于 进程.线程,都是有内核进行调度,有 CPU 时间片的概念,进行 抢占式调度(有多种调度算法) (补充: 抢占式调度与非抢占(轮询 ...
- Django_静态文件的配置(STATIC_URL)
静态文件,常用在head中,可动态的去检索settings里面的STATIC_URL = '/static/',然后做拼接settings.py中 STATIC_URL = '/static9/' # ...
- Action<T>和Func<T>委托事例
Action<T>和Func<T>委托事例 using System; //除了为每个参数和返回类型定义一个新委托类型之外,还可以使用Action<T>和Func& ...
- Beginning Linux Programming 学习--chapter 17 Programming KDE using QT
KDE: KDE,K桌面环境(K Desktop Environment)的缩写.一种著名的运行于 Linux.Unix 以及FreeBSD 等操作系统上的自由图形桌面环境,整个系统采用的都是 Tro ...
- 《Mysql - 幻读》
一:准备 - 为了深入了解幻读,准备数据. CREATE TABLE `t` ( `id` ) NOT NULL, `c` ) DEFAULT NULL, `d` ) DEFAULT NULL, PR ...