Ефективний алгоритм для обчислення го числа Фібоначчі


11

- го числа Фібоначчі може бути обчислений в лінійний час з використанням наступного повторення:n

def fib(n):
    i, j = 1, 1
    for k in {1...n-1}:
        i, j = j, i+j
    return i

- го числа Фібоначчі також може бути обчислена як . Однак це має проблеми з питаннями округлення навіть для порівняно невеликих . Ймовірно, є способи цього, але я б краще цього не робив.[ φ n / nн[φn/5]n

Чи існує ефективний (логарифмічний у значенні або кращий) алгоритм для обчислення го числа Фібоначчі, який не покладається на арифметику з плаваючою комою? Припустимо, що цілі операції ( , , , ) можна виконувати в постійний час.n + - × /nn+×/


5
Як пропозиція, стаття Вікіпедії про числа Фібоначчі має безліч методів.
Псевдонім

пор. stackoverflow.com/questions/14661633/… та посилання на них та навколо.
Буде Несс

Відповіді:


14

Ви можете використовувати матричне живлення та ідентифікацію У вашій моделі обчислення це алгоритм , якщо ви використовуєте повторне квадратування для здійснення живлення.O(журналn)

[1110]n=[Fn+1FnFnFn1].
O(logn)

1
Це класика.
dfeuer

8
Ви також можете використовувати цю ідентичність для отримання повторень і . F2n1=Fn2+Fn12F2n=Fn2+2Fn1Fn
аугурар

4

Ви можете прочитати цю математичну статтю: Швидкий алгоритм обчислення великих чисел Фібоначчі (Дайсуке Такахасі): PDF .

Простіше кажучи, я реалізував кілька алгоритмів Фібоначчі в C ++ (без та з GMP) та Python. Повні джерела на Bitbucket. На головній сторінці ви також можете переходити посилання на:

  • Інтернет-документація C ++ HTML.
  • Маленький математичний документ: числа Фібоначчі - кілька відношень для реалізації хороших алгоритмів

Найбільш корисні формули:

  • F2n=Fn+12Fn12=2FnFn1+Fn2
  • F2n+1=Fn+12+Fn2

Будьте уважні до алгоритму. Ви не повинні обчислювати одне і те ж значення кілька разів. Простий рекурсивний алгоритм (в Python):

def fibonacci_pair(n):
    """Return (F_{n-1}, F_n)"""
    if n != 0:
        f_k_1, f_k = fibonacci_pair(n//2)  # F_{k-1},F_k with k = n/2

        return ((f_k**2 + f_k_1**2,
                 ((f_k*f_k_1)*2) + f_k**2) if n & 1 == 0  # even
                else (((f_k*f_k_1)*2) + f_k**2,
                      (f_k + f_k_1)**2 + f_k**2))
    else:
        return (1, 0)

Його складність логарифмічна (якщо основні операції знаходяться в постійному часі): .O(logn)


2
Ласкаво просимо до інформатики . Чи можете ви додати більше інформації у відповідь? На даний момент це не більше ніж два посилання, тому ваша відповідь стане безглуздою, якщо ці посилання вмирають або сервери, на яких вони є, недоступні. Посилання на додаткову інформацію є нормальними, але посилання тут є єдиною інформацією. Крім того, зауважте, що питання точно визначено алгоритмами, а не реалізацією C ++. Реалізація, як правило, затуляє алгоритми, що лежать в основі деталей, орієнтованих на мову.
Девід Річербі

Девід, перша посилання - це посилання на математичну статтю. Заголовок Швидкий алгоритм [...] відповідає на запитання "Чи є ефективний (логарифмічний у значенні n або краще) алгоритм [...]?" Друга посилання - це посилання на мої різні реалізації, в C ++ та Python, і невеликий математичний документ з кількома формулами.
Олів'є Пірсон

2
Ні, назва статті, яка містить вашу відповідь, нічого не відповідає. Текст статті, який ваш відповідь не містить майже ніяких, здається , що це , ймовірно , робить відповідь на питання. Але Stack Exchange - це сайт із запитаннями та відповідями, а не фермерська посилання. (І ні, я не пропоную вам скопіювати вставити статтю у свою відповідь. Але потрібна резюме.)
Девід Річербі,

Якщо ви хочете резюме, напишіть його!
Олів'є Пірсон

0

Основна теорія та код для обчислення лінійних повторень з постійними коефіцієнтами в доступні на веб-сайті http://www.jjj.de/ .O(log2n)

Перевірте безкоштовну книгу « Матеріальні обчислення» та код pari / gp.


5
Краще узагальнити ідеї, а не просто розміщувати посилання.
аугурар
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.