Еще один алгоритм вычисления чисел Фибоначчи

в 13:52, , рубрики: Алгоритмы, числа фибоначчи, метки:

Перед прочтением статьи, решил попробовать придумать свой алгоритм. Времени понадобилось не очень много. Ниже описание идеи и пример на С++.

Достаточно просто получить вот такую формулу:
Еще один алгоритм вычисления чисел Фибоначчи, где Еще один алгоритм вычисления чисел Фибоначчи

Формула доказывается легко по индукции. При m = 0 формула верна:
Еще один алгоритм вычисления чисел Фибоначчи
Предположим, что формула верна при m = p
Еще один алгоритм вычисления чисел Фибоначчи
Докажем, что формула верна при m = p + 1:
Еще один алгоритм вычисления чисел Фибоначчи
— получили такое же выражение, как и для случая m = p, т.е. при m = p + 1 формула остается верной
Легко получить Еще один алгоритм вычисления чисел Фибоначчи через те же числа:
Еще один алгоритм вычисления чисел Фибоначчи
При нечетном N, m можно подобрать так, чтобы выполнялись равенства Еще один алгоритм вычисления чисел Фибоначчи и Еще один алгоритм вычисления чисел Фибоначчи. Это число равно Еще один алгоритм вычисления чисел Фибоначчи
После упрощения получаем такие формулы:
Еще один алгоритм вычисления чисел Фибоначчи
Еще один алгоритм вычисления чисел Фибоначчи
Еще один алгоритм вычисления чисел Фибоначчи

Используя последние формулы можно получить простой рекурсивный алгоритм.

#include <iostream>
using namespace std;

void factorial_recursive(int n, int& fn, int& fn1)
{
    int gn, gn1;
    if (n < 2) {
        fn = n;
        fn1 = 1; 
        return; 
    } 
    factorial_recursive(n / 2, gn, gn1);
    if (n % 2) {
        fn = gn1 * gn1 + gn * gn;
        fn1 = gn1 * gn1 + 2 * gn * gn1;
    } else {
        fn = 2 * gn * gn1 - gn * gn;
        fn1 = gn1 * gn1 + gn * gn;
    }
}

int factorial(int n)
{
    int fn, fn1;
    factorial_recursive(n, fn, fn1);
    return fn;
}

int main()
{
   for (int i = 0; i < 20; i++)
     cout << factorial(i) << " ";
   return 0;
}

От рекурсии уйти достаточно просто:

#include <iostream>
using namespace std;

unsigned factorial(unsigned n)
{
    if (n < 2)
        return n;
    unsigned mask = 1, m = n;
    while (m > 1) {
        m >>= 1;
        mask <<= 1;
    }
    unsigned fn = 1, fn1 = 1, gn, gn1;
    while (mask > 1) {
        mask >>= 1;
        gn = fn;
        gn1 = fn1;
        if (n & mask) {
            fn = gn1 * gn1 + gn * gn;
            fn1 = gn1 * gn1 + 2 * gn * gn1;
        } else {
            fn = 2 * gn * gn1 - gn * gn;
            fn1 = gn1 * gn1 + gn * gn;
        }
    }
    return fn;
}

int main()
{
   for (int i = 0; i < 20; i++)
     cout << factorial(i) << " ";
   return 0;
}

Автор: alexeibs

* - обязательные к заполнению поля