Как вычислить числа Фибоначчи: решение по шагам
Дано: рекуррентная формула с началом , и номер члена . Найти: значение , проверку по формуле Бине и число вызовов наивной рекурсии.
Ряд проходится один раз в цикле, причём хранить нужно только два последних члена, а результат сверяется с . Ответ: , цикл делает 29 сложений, наивная рекурсия на том же номере - 2 692 537 вызовов. Калькулятор сверху пересчитывает всё это для любого номера и другого начала ряда, ниже - решение по шагам.
Решение по шагам
Дано. Последовательность задана рекуррентно:
Найти: , проверку независимым способом и цену наивной рекурсии.
Шаг 1. Выписываем начало ряда. Правило не требует ничего, кроме двух предыдущих членов, поэтому первые значения получаются устным счётом:
| k | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| F(k) | 0 | 1 | 1 | 2 | 3 | 5 | 8 | 13 | 21 | 34 | 55 |
Отсюда уже видно, что ряд растёт быстро, но не как степень двойки: , тогда как . Скорость роста определяет золотое сечение, к этому вернёмся после решения.
Шаг 2. Идём по ряду итеративно. Держать весь массив незачем: для очередного члена хватает двух предыдущих. Заводим переменные и и сдвигаем их ровно раз:
a, b = 0, 1 # F(0) и F(1)
for _ in range(n - 1): # при n = 30 это 29 шагов
a, b = b, a + b
# после цикла b = F(n)
Проверить число шагов легко на краю: при цикл не выполняется ни разу и остаётся равным . Значит, для тридцатого члена нужно 29 сложений, а не 30. Хвост прохода выглядит так:
| k | 25 | 26 | 27 | 28 | 29 | 30 |
|---|---|---|---|---|---|---|
| F(k) | 75 025 | 121 393 | 196 418 | 317 811 | 514 229 | 832 040 |
Последнее сложение цикла - это .
Шаг 3. Проверяем результат формулой Бине. Формула выражает член ряда через золотое сечение и не опирается на предыдущие значения:
Подставляем . Первое слагаемое: , делим на и получаем . Второе слагаемое по модулю равно , то есть намного меньше половины единицы. Поэтому ответ - просто округление первого слагаемого:
Два независимых способа дали одно и то же число, значит, в проходе по ряду ошибки нет.
Шаг 4. Считаем, во что обошлась бы наивная рекурсия. Функция, которая честно вызывает себя дважды на каждом уровне, делает вызовов, а это ровно :
Против 29 сложений в цикле это больше почти в 93 тысячи раз, и разрыв растёт с каждым следующим номером.
Ответ: . Формула Бине даёт то же значение, итеративный проход стоит 29 сложений, а наивная рекурсия без запоминания промежуточных результатов - 2 692 537 вызовов.
Формула и откуда она берётся
Рекуррентность линейна и однородна, поэтому у неё есть решение в виде геометрической прогрессии. Подставим пробное и сократим на :
Это характеристическое уравнение ряда. Его корни и - те самые числа из формулы Бине; первый из них и есть золотое сечение. Любая комбинация удовлетворяет рекуррентности, а начальные условия выбирают из этого семейства единственную последовательность.
Из следует , из получается . Подставив , имеем , а разность корней равна . Отсюда и , что и даёт формулу из шага 3.
Ключевая деталь - модуль второго корня: , поэтому убывает и уже при вклад этого слагаемого меньше сотой доли единицы. Значит, при любом достаточно взять первое слагаемое и округлить его до ближайшего целого. Тот же вывод получается через производящие функции: там ряд Фибоначчи сворачивается в дробь , и разложение на простейшие дроби приводит к тем же и - подробный разбор этого пути есть в статье про метод производящих функций.
Быстрый способ: удвоение вместо прохода по всему ряду
Когда номер большой, 29 сложений превращаются в миллион, и проход по ряду перестаёт быть быстрым. Тогда используют тождества удвоения, которые сразу перепрыгивают от номера к номеру :
Проверим их на нашей задаче. Возьмём , где и :
Совпало с итеративным ответом. Попутно получается и соседний член: - то самое число, которое понадобилось в шаге 4. Рекурсия по этим тождествам делает порядка шагов: для это пять удвоений вместо двадцати девяти сложений.
Та же идея в матричной записи: возведение матрицы в степень даёт в углах числа , и , а сама степень считается двоичным алгоритмом. Механика обоих приёмов разобрана в задачах про быстрое возведение в степень и возведение матрицы в степень.
Отношение соседних чисел и золотое сечение
Разделим каждый член на предыдущий: , , , , , , , - значения скачут то выше, то ниже, но размах быстро сжимается. На тридцатом номере отношение уже неотличимо от золотого сечения на глаз:
Причина видна из формулы Бине. Поделив на , получаем плюс поправку порядка , а отношение меньше единицы. Знак поправки меняется с каждым шагом, потому что отрицателен, - отсюда и колебания вокруг предела. Переключи график калькулятора сверху в режим отношения: линия видимо прижимается к пунктиру золотого сечения примерно к десятому номеру.
Правило сохраняется и для других начальных значений. Если взять , , получатся числа Люка - ряд другой, а предел отношения тот же, потому что характеристическое уравнение не изменилось. Меняются только коэффициенты и .
Частые ошибки
- Сдвиг нумерации. Часть учебников начинает ряд с , и тогда «тридцатое число» оказывается нашим . В ответе всегда указывай, от какого начала считал.
- Лишняя итерация в цикле. Проход из шагов вместо выдаёт . Проверяй цикл на краю: при он не должен выполниться ни разу.
- Наивная рекурсия на больших номерах. При дерево вызовов разрастается до - программа зависает. Лечится одной строкой с запоминанием уже посчитанных значений, см. динамическое программирование.
- Переполнение целого типа. Числа растут экспоненциально: - последний член, помещающийся в 64-битное знаковое целое, а уже выходит за предел и даёт мусор без всякого предупреждения.
- Слепая вера в формулу Бине в программе. В арифметике с плавающей точкой теряет младшие разряды, и примерно после семидесятого номера округление начинает давать не тот ответ. Для больших нужны целочисленные способы: цикл или удвоение.
- Путаница с числами Люка. Ряд подчиняется тому же правилу, но это не числа Фибоначчи; сверяй первые члены с условием задачи.
FAQ
Чему равны и ? В общепринятой нумерации и , дальше . Эта версия удобна тем, что формула Бине работает без поправок, а тождества удвоения не требуют отдельных оговорок для нулевого члена.
Можно ли считать числа Фибоначчи прямо по формуле Бине? Для небольших номеров - да, округление даёт точный ответ. Но double хранит около шестнадцати значащих цифр, поэтому примерно с семидесятого номера результат расходится с истинным. Если номер большой, считай целыми числами.
Почему наивная рекурсия работает так медленно? Она пересчитывает одни и те же подзадачи заново: вычисляется дважды, - трижды, и число вызовов растёт как . Это классический пример экспоненциальной сложности, разбор оценки такого кода есть в задаче про сложность алгоритма.
Как найти ? Понадобится длинная арифметика: в этом числе 209 десятичных цифр. Алгоритм - удвоение или матричная степень, они дадут ответ примерно за десять шагов умножения длинных чисел, тогда как обычный цикл потребует тысячи сложений.
Коротко
- Числа Фибоначчи заданы правилом при , .
- Итеративный проход хранит два числа и делает сложение: для это 29 шагов и результат .
- Проверка формулой Бине: - округление , где - золотое сечение; для тридцатого номера она даёт то же .
- Формула выводится из характеристического уравнения , а второй корень быстро исчезает, потому что .
- Наивная рекурсия стоит вызовов, тождества удвоения - около пяти шагов; отношение соседних членов равно против .
Похожие задачи
Как определить сложность алгоритма: пошаговое решение
Как определить сложность алгоритма по коду: считаем итерации вложенных циклов и цикла с делением пополам, оставляем главный член, проверяем оценку удвоением n и кратко разбираем основную теорему.
Программирование/алгоритмыКак реализовать дек: пошаговое решение
Как реализовать дек на кольцевом массиве: формулы индексов head и tail через остаток от деления, трассировка push и pop с обоих концов, вариант на двусвязном списке, сложность операций.
Программирование/алгоритмыКак сложить числа в двоичной системе: разбор столбиком
Как сложить двоичные числа столбиком: правило для одного разряда, перенос в старший разряд, трассировка по всем восьми битам, проверка через десятичную систему и переполнение байта.
Орг./аналит. химияОкисление перманганатом калия: реакции в трёх средах
Как написать окисление перманганатом калия в кислой, нейтральной и щелочной средах: продукты восстановления марганца, метод электронного баланса, расстановка коэффициентов, расчёт титранта.
Химия (физич./структурная)Как найти активность иона: расчёт по Дебаю-Хюккелю
Как найти активность иона в растворе: ионная сила по всем ионам, коэффициент активности по предельному закону Дебая-Хюккеля, произведение f на c, разбор с числами и калькулятор.
ГенетикаКак найти частоту генотипов: закон Харди-Вайнберга
Разбор задачи по популяционной генетике: как найти частоту генотипов по закону Харди-Вайнберга, формула p2 плюс 2pq плюс q2, расчёт числа особей и калькулятор частот.