【问题标题】:optimizing code: fibonacci algorithm优化代码:斐波那契算法
【发布时间】:2015-10-16 13:19:01
【问题描述】:

我正在为非常大的数字(第 10 万个数字)研究斐波那契算法。我需要让它运行得更快,但只需几秒钟,我就没有想法了。有没有办法让它更快?感谢您的帮助。

#include <iostream>

using namespace std;
int main() {


    string elem_major = "1";
    string elem_minor = "0";
    short elem_maj_int;
    short elem_min_int;
    short sum;
    int length = 1;
    int ten = 0;

    int n;
    cin >> n;


    for (int i = 1; i < n; i++)
    {

        for (int j = 0; j < length; j++)
        {
            elem_maj_int = short(elem_major[j] - 48);
            elem_min_int = short(elem_minor[j] - 48);
            sum = elem_maj_int + elem_min_int + ten;
            ten = 0;
            if (sum > 9)
            {
                sum -= 10;
                ten = 1;
                if (elem_major[j + 1] == NULL)
                {
                    elem_major += "0";
                    elem_minor += "0";
                    length++;
                }
            }
            elem_major[j] = char(sum + 48);
            elem_minor[j] = char(elem_maj_int + 48);
        }
    }

    for (int i = length-1; i >= 0; i--)
    {
        cout << elem_major[i];
    }

    return 0;
}

【问题讨论】:

  • 这个问题属于Code Review
  • 使用矩阵的幂。
  • @sam2090 这是 DP 方法

标签: c++ algorithm fibonacci


【解决方案1】:

无论您对给定代码进行了多么好的优化,在不更改底层算法的情况下,您只能稍微优化它。您的方法具有线性复杂性,对于较大的值,它会很快变慢。斐波那契数的更快实现是在矩阵上做矩阵exponentiation by squaring

0 1
1 1

这种方法将具有渐近更好的对数复杂度。对该矩阵执行几次幂运算,您会注意到 n + 1st 斐波那契数位于其右下角。

【讨论】:

【解决方案2】:

我建议您对大数字使用类似 cpp-bigint (http://sourceforge.net/projects/cpp-bigint/) 的东西。 代码看起来像这样

#include <iostream>
#include "bigint.h"

using namespace std;
int main() {
    BigInt::Rossi num1(0);
    BigInt::Rossi num2(1);
    BigInt::Rossi num_next(1);

    int n = 100000;

    for (int i = 0; i < n - 1; ++i)
    {
        num_next = num1 + num2;
        num1 = std::move(num2);
        num2 = std::move(num_next);
    }
    cout << num_next.toStrDec() << endl;
    return 0;
}

在我的机器上进行快速基准测试:

time ./yourFib
real    0m8.310s
user    0m8.301s
sys 0m0.005s

time ./cppBigIntFib
real    0m2.004s
user    0m1.993s
sys 0m0.006s

【讨论】:

    【解决方案3】:

    我会保存一些预先计算的点(特别是因为您正在寻找非常大的数字)

    即说我保存了第 500 个和第 501 个 fib 号码。那么如果有人问我第 600 个小谎言是什么?我会从 502 而不是从 1 开始计算。这真的可以节省时间。

    现在的问题是您将节省多少积分以及如何选择要保存的积分?

    这个问题的答案完全取决于应用程序和可能的分布。

    【讨论】:

      猜你喜欢
      • 2012-06-11
      • 1970-01-01
      • 2017-08-24
      • 2013-02-09
      • 1970-01-01
      • 1970-01-01
      • 2013-03-31
      • 2016-09-11
      • 1970-01-01
      相关资源
      最近更新 更多