Java实现斐波那契数列以及int取值溢出问题详解

本文介绍了斐波那契数列的概念,并提供了Java语言的递归与for循环两种实现方式。讨论了在计算较大斐波那契数时int类型的取值溢出问题,建议使用Long或BigInteger以避免溢出。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、斐波那契数列是什么?

这里借鉴百度百科一下下:

  • 斐波那契数列(Fibonacci sequence),又称黄金分割数列、因数学家莱昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:0、1、1、2、3、5、8、13、21、34、
  • 在数学上,斐波那契数列以如下被以递推的方法定义:F(0)=0,F(1)=1, F(n)=F(n - 1)+F(n - 2)(n ≥ 2,n∈ N*)
  • 在现代物理、准晶体结构、化学等领域,斐波纳契数列都有直接的应用,为此,美国数学会从 1963年起出版了以《斐波纳契数列季刊》为名的一份数学杂志,用于专门刊载这方面的研究成果。
    很明显:这个数列从第3项开始,每一项都等于前两项之和

二、java代码实现:当输入n时,会获取斐波那契数列的第n个数的值。

  • 递归实现:
    这里可以很明显看出,通过递归第50个数已经用时31秒多,效率实在太低了。
    int的取值范围有限,最大值为 (2^32)-1 = 2147483647,值太大时会发生取值范围溢出的情况。
    可以换成Long类型,不过溢出也是迟早的事情。
public class FibonacciTest {
    public static void main(String[] args) {
        // 获取当前时间戳
        long currentTimeMillis1 = System.currentTimeMillis();

        // 调用阶乘方法实现斐波那契数列
        System.out.println("第50个数是: " + fibonacci(50));

        // 获取计算过的当前时间戳
        long currentTimeMillis2 = System.currentTimeMillis();

        // 获取结果用时多少
        System.out.println("递归实现用时" + (currentTimeMillis2 - currentTimeMillis1) + "毫秒");

    }

    // 前两个数比较特殊
    public static int fibonacci(int n) {
        if(n == 1) {
            // 第一个数给定为0,当然也可以指定别的数字
            return 0;
        }else if (n == 2){
            // 第二个数给定为1,当然也可以指定别的数字
            return 1;
        }else if (n > 2){
            return fibonacci(n-1) + fibonacci(n-2);
        }else {
            // 如果输入的n为负数,返回-1
            return -1;
        }
    }
}

在这里插入图片描述

  • for循环实现:
    这里是用的Long类型的,计算第50个数只用了2毫秒,这个效率就很nice了!!!不过再计算后面的数还是会出现溢出的情况
public class FibonacciTest {
    public static void main(String[] args) {
        // 获取当前时间戳
        long currentTimeMillis1 = System.currentTimeMillis();

        // 调用for循环方法实现斐波那契数列
        System.out.println(fibonacci(50));

        // 获取计算过的当前时间戳
        long currentTimeMillis2 = System.currentTimeMillis();

        // 获取结果用时多少
        System.out.println("for循环用时" + (currentTimeMillis2 - currentTimeMillis1) + "毫秒");

    }
    
    // 前两个数比较特殊
    public static Long fibonacci(int n) {
        if (n == 1){
            // 第一个数给定为0,当然也可以指定别的数字
            return 0L;
        }else if (n == 2){
            // 第二个数给定为1,当然也可以指定别的数字
            return 1L;
        }else if (n > 2){
            //定义三个Long类型整数,first表示指定的第一个数,second表示指定的第二个数,sum表示第n个数
            long first =0L, second= 1L, sum =0L;
            // 前两个数没有规律,直接给定,所以不参加循环
            for (int i = 0; i < n - 2; i++) {
                // 根据第三个数的值等于前两个数的和的规律
                sum = first + second;
                //第2个数的值赋值给第1个数
                first = second;
                //第3个数的值赋值给第2个数
                second = sum;
                System.out.println("第" + i + "个数为:  " + sum);
            }
            return  sum;
        }else {
            // 如果输入的n为负数,返回-1
            return -1L;
        }
    }
}

在这里插入图片描述

  • 接下来完善一下取值溢出的问题:
    BigInteger类型的数字范围较Integer,Long类型的数字范围要大得多,它支持任意精度的整数,也就是说在运算中 BigInteger 类型可以准确地表示任何大小的整数值而不会丢失任何信息。
import java.math.BigInteger;

public class FibonacciTest {
    public static void main(String[] args) {
        // 获取当前时间戳
        long currentTimeMillis1 = System.currentTimeMillis();

        // 调用for循环方法实现斐波那契数列
        System.out.println(fibonacci(500));

        // 获取计算过的当前时间戳
        long currentTimeMillis2 = System.currentTimeMillis();

        // 获取结果用时多少
        System.out.println("for循环实现用时" + (currentTimeMillis2 - currentTimeMillis1) + "毫秒");

    }

    // 前两个数比较特殊
    public static BigInteger fibonacci(int n) {
        // 实例化BigInteger 
        BigInteger bigInteger = new BigInteger(String.valueOf(n));
        if (n == 1) {
            // 第一个数给定为0,当然也可以指定别的数字
            return BigInteger.valueOf(0);
        } else if (n == 2) {
            // 第二个数给定为1,当然也可以指定别的数字
            return BigInteger.valueOf(1);
        } else if (n > 2) {
            //定义三个long类型整数,first表示指定的第一个数,second表示指定的第二个数,sum表示第n个数
            BigInteger first = BigInteger.valueOf(0),
                    second = BigInteger.valueOf(1),
                    sum = BigInteger.valueOf(0);
            // 前两个数没有规律,直接给定,所以不参加循环
            for (int i = 0; i < n - 2; i++) {
                // 根据第三个数的值等于前两个数的和的规律
                sum = first.add(second);
                //第2个数的值赋值给第1个数
                first = second;
                //第3个数的值赋值给第2个数
                second = sum;
                System.out.println("第" + i + "个数为:  " + sum);
            }
            return sum;
        } else {
            // 如果输入的n为负数,返回-1
            return BigInteger.valueOf(-1);
        }
    }
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值