【Java】打印斐波那契数列效率和错误性的问题

一、问题

下面用了6种方法打印斐波那契数列的前50项:
1、普通方法
2、数组方法
3、集合方法
4、递归方法
5、Map方法
6、BigDecimal方法

二、源码

结合网上的方法,再加上同事同学提供的建议,加上自己的研究,源代码如下:

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class fibonacciTest {
    public static void main(String[] args) {
        int length=1000;


        long t1=System.currentTimeMillis();
        //1、普通打印
        fibonacciOrdinary(length);
        long t2=System.currentTimeMillis();

        //2、数组打印
        fibonacciMethodOfArray(length);
        long t3=System.currentTimeMillis();

        //3、集合打印
        fibonacciMethodOfList(length);
        long t4=System.currentTimeMillis();

        //4、递归打印
        //fibonacciMethodOfRecursive(length);
        long t5=System.currentTimeMillis();

        //5、Map打印
        fibonacciMethodOfMap(length);
        long t6=System.currentTimeMillis();

        //6、测试
        fibonacciMethodOfBigDecimal(length);
        long t7= System.currentTimeMillis();


        System.out.println("普通方法耗时:"+(t2-t1)+"ms");
        System.out.println("数组方法耗时:"+(t3-t2)+"ms");
        System.out.println("集合方法耗时:"+(t4-t3)+"ms");
        System.out.println("递归方法耗时:"+(t5-t4)+"ms");
        System.out.println("Map方法耗时:"+(t6-t5)+"ms");
        System.out.println("BigDecimal方法耗时:"+(t7-t6)+"ms");

    }

    /****************************************************/
    //普通
    private static void  fibonacciOrdinary(int length){
        double a = 1, b = 1, c = 2;
        System.out.println("【普通方法】斐波那契数列前"+length+"项为:");
        System.out.println("第"+1+"项:"+a);
        System.out.println("第"+2+"项:"+b);
        //因为前面还有两个1、1 所以i<=18
        for (int i = 1; i < length; i++) {
            c = a + b;
            a = b;
            b = c;
            System.out.println("第"+(i+1)+"项:"+c);
        }
    }


    /***************************************************/
    //数组,有问题
    private static void fibonacciMethodOfArray(int length){
        double array [] = new double[length];
        array[0] = 1.0;
        array[1] = 1.0;
        for (int i=2;i<length;i++){
            array[i]=array[i-1]+array[i-2];
        }
        System.out.println("【数组方法】斐波那契数列前"+length+"项如下所示:");
        for (int i=0;i<length;i++){
            System.out.println("第"+(i+1)+"项:"+array[i]);
        }
    }


    /************************************************/
    //集合
    private static void fibonacciMethodOfList(int length){
        List<Double> longList = new ArrayList<>();
        longList.add(1.0);
        longList.add(1.0);
        System.out.println("【集合方法】斐波那契数列前"+length+"项如下:");
        for (int i=2;i<length;i++){
            longList.add(longList.get(i-1)+longList.get(i-2));
        }
        for (int i=0;i<length;i++){
            System.out.println("第"+(i+1)+"项的值为:"+longList.get(i));
        }
    }

    /************************************************/
    //递归;效率明显偏低
    private static void fibonacciMethodOfRecursive (long length){
        System.out.println("【递归方法】斐波那契数列的前"+length+"项为:");
            for (int j = 1; j <= length; j++) {
                System.out.println("第"+j+"项:"+getFibonacci(j));
            }
    }

    private static int getFibonacci(int i) {
        if (i == 1 || i == 2)
            return 1;
        else
            return getFibonacci(i - 1) + getFibonacci(i - 2);
    }

    /************************************/
    //Map
    private static void fibonacciMethodOfMap(int length){
        System.out.println("【Map方法】斐波那契数列的前"+length+"项为:");
        Map<Integer,String> array  = new HashMap<>(1000,1f);
            array.put(0, "1");
            array.put(1, "1");
            array.put(2, "2");
            for (int i=3;i<=length;i++){
                BigDecimal decimal1 = new BigDecimal(array.get(i-1));
                BigDecimal decimal2 = new BigDecimal(array.get(i-2));
                array.put(i, decimal1.add(decimal2).toString());
            }
            for (int i=0;i<length;i++){
                System.out.println("第"+(i+1)+"项:"+array.get(i));
            }
    }

    /************************************/
    //测试
    private static void  fibonacciMethodOfBigDecimal(int length){
        System.out.println("【BigDecimal方法】斐波那契数列的前"+length+"项为:");
        BigDecimal decimal1 = new BigDecimal(1);
        BigDecimal decimal2 = new BigDecimal(1);
        BigDecimal decimal;
        for (int i=2;i<=length;i++){

            if (i==1){
                System.out.println("第1项"+decimal1);
            }else if (i==2){
                System.out.println("第2项"+decimal2);
            }else {
                decimal=decimal2.add(decimal1);
                decimal1=decimal2;
                decimal2=decimal;
                System.out.println("第"+i+"项"+decimal);
            }
        }
    }

}

三、结果

打印斐波那契前1000个数结果如下:

普通方法耗时:243ms
数组方法耗时:162ms
集合方法耗时:80ms
//递归方法耗时:0ms
Map方法耗时:293ms
BigDecimal方法耗时:97ms

四、分析

4.1、【效率性】从效率上看,数组,集合,BigDecimal方法较为快速;但是这里有个不确定因素就是机器性能是不是平均的,并且打印耗时也是很严重的,所以上面的结果仅供参考;集合等方法虽然快,但是不适合大数字的计算;递归方法太慢,是不合适的;

4.2、【正确性】

普通方法,数组方法,集合方法不能高位数计算; 而Map方法,BigDecimal方法均使用了BigDecimal,所以可以高位数计算; 而BigDecimal又剥离了Map外衣,所以大数据量建议用后两种方法;

	//BigDecimal方法
    private static void  fibonacciMethodOfBigDecimal(int length){
        System.out.println("【BigDecimal方法】斐波那契数列的前"+length+"项为:");
        BigDecimal decimal1 = new BigDecimal(1);
        BigDecimal decimal2 = new BigDecimal(1);
        BigDecimal decimal;
        for (int i=2;i<=length;i++){

            if (i==1){
                System.out.println("第1项"+decimal1);
            }else if (i==2){
                System.out.println("第2项"+decimal2);
            }else {
                decimal=decimal2.add(decimal1);
                decimal1=decimal2;
                decimal2=decimal;
                System.out.println("第"+i+"项"+decimal);
            }
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

陶洲川

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值