C++实现斐波那契数列

来源:互联网 发布:sketchuppro2018 mac 编辑:程序博客网 时间:2024/05/18 03:37

斐波那契数列:

1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233,377,610,987,1597,2584,4181,6765,10946,17711,28657,46368........


长相简单,实现简单,网上童鞋们的搞法多数都是直观的递归,逐个计算实现GetFibonacciSequenceItemByIndex2

那么如果只想单独计算数列中第n个数的值,递归方式看起来就很冗余。

于是查了查斐波那契数列中元素的计算方式:


就有了下面的函数GetFibonacciSequenceItemByIndex。


#include "stdafx.h"#include <math.h>#include <time.h>#include <iostream>#define TIMER_START() clock_t start = clock();#define TIMER_END() clock_t end = clock();#define TIMER_COUNT() (double)(end - start)/ CLOCKS_PER_SEC;#define TIMER_OUTPUT() std::cout <<"Running Time : "<<(double)(end - start)/*/ CLOCKS_PER_SEC*/ << std::endl;long double GetFibonacciSequenceItemByIndex3(int n){    long double x = 0;    long double a1 = 1;    long double a2 = 1;    for (int nn = 1; nn <= n; ++nn)    {        if (nn == 1)        {            x = a1;        }        else if (nn == 2)        {            x = a2;        }         else        {            x = a1 + a2;            a1 = a2;            a2 = x;        }    }    return x;}long double GetFibonacciSequenceItemByIndex2(int n){    long double x = 0;    if (n == 1)    {        x = 1;    }    else if (n == 2)    {        x = 1;    }     else    {        x = GetFibonacciSequenceItemByIndex2(n-1) + GetFibonacciSequenceItemByIndex2(n-2);    }    return x;}long double GetFibonacciSequenceItemByIndex(int n){    static const double v5 = pow(5, 0.5);    long double x = 0;    x = (pow((1 + v5) / 2, n) - pow((1 - v5) / 2, n)) / v5;    return x;}void FiSeCompare(int s, int e){    {        TIMER_START()            for (int n = s; n < e; ++n)            {                //int i = 1000;                //while (i)                //{                    long double x = GetFibonacciSequenceItemByIndex2(n);                //    i--;                //}                //printf("%0.0f, ", x);            }            TIMER_END()                std::cout << "non-pow : " << s << " - " << e << std::endl;            TIMER_OUTPUT()                std::cout << std::endl;    }    {        TIMER_START()            for (int n = s; n < e; ++n)            {                //int i = 1000;                //while (i)                //{                    long double x = GetFibonacciSequenceItemByIndex(n);                //    i--;                //}                //printf("%0.0f, ", x);            }            TIMER_END()                std::cout << "pow : " << s << " - " << e << std::endl;            TIMER_OUTPUT()                std::cout << std::endl;    }}int _tmain(int argc, _TCHAR* argv[]){    FiSeCompare(1, 30);    FiSeCompare(301, 330);    FiSeCompare(601, 630);    FiSeCompare(1, 1001);    return 0;}


尴尬的事情来了… 尼玛pow应该也是递归实现的吧(虽然并不知道具体怎么实现的)… 

好吧,测测效率,比较一下。




分析结果之前先说下测试时候遇到的坑吧… 

尼玛long double都不够用啊,真的不够用啊! 本来想测10000到13000, 50000到53000,这我还算是搂着测的,结果居然输出的全是1… 测试结果只能扔…


结果发现也就只能测到1000+的位置就是极限了,好吧… 你妹啊!居然耗时都变成0了… 好,我忍,每个位置的数都给我算1000遍,累死你个****。

结果就变身上面辣样咯。


不墨迹了,结论: (前提:不讨论数列中连续元素段的算法优化可能性)

1. 递归方式(non-pow): 元素位置越靠后,计算效率越差。不测也知道是这样咯…

2. 使用pow函数: 计算效率与元素位置无关,至于调用次数有关。难道说,pow函数的实现方式并不是用递归?!有大神吗,求解啊!

3. 果然还是少用递归才是王道啊~ 哈哈哈哈哈~


P.S. 递归真的是不能用啊,完全没有效率可言… 用循环算法也比递归快的多的多的多啊