Как найти элемент последовательности фибоначчи

Текущая версия страницы пока не проверялась опытными участниками и может значительно отличаться от версии, проверенной 21 декабря 2022 года; проверки требуют 33 правки.

Черепица с квадратами, длина сторон которых является последовательными числами Фибоначчи: 1, 1, 2, 3, 5, 8, 13 и 21

Спираль Фибоначчи: приближение золотой спирали, созданной путём рисования круговых дуг, соединяющих противоположные углы квадратов в мозаике Фибоначчи;[1] (см. предыдущее изображение)

Чи́сла Фибона́ччи (вариант написания — Фибона́чи[2]) — элементы числовой последовательности

0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946, 17711, … (последовательность A000045 в OEIS),

в которой первые два числа равны 0 и 1, а каждое последующее число равно сумме двух предыдущих чисел[3]. Названы в честь средневекового математика Леонардо Пизанского (известного как Фибоначчи)[4].

Правда, в некоторых книгах, особенно в старых[каких?], член F_{0}, равный нулю, опускается — тогда последовательность Фибоначчи начинается с {displaystyle F_{1}=F_{2}=1}[5][6].

Говоря более формально, последовательность чисел Фибоначчи {displaystyle {F_{n}}} задаётся линейным рекуррентным соотношением:

{displaystyle F_{0}=0,quad F_{1}=1,quad F_{n}=F_{n-1}+F_{n-2}},
где {displaystyle  ngeqslant 2, nin mathbb {Z} }.

Иногда числа Фибоначчи рассматривают и для отрицательных значений n как двусторонне бесконечную последовательность, удовлетворяющую тому же рекуррентному соотношению. Соответственно, члены с отрицательными индексами легко получить с помощью эквивалентной формулы «назад»: {displaystyle F_{n}=F_{n+2}-F_{n+1}}:

n −10 −9 −8 −7 −6 −5 −4 −3 −2 −1 0 1 2 3 4 5 6 7 8 9 10
F_{n} −55 34 −21 13 −8 5 −3 2 −1 1 0 1 1 2 3 5 8 13 21 34 55

Легко заметить, что {displaystyle F_{-n}=(-1)^{n+1}F_{n}}.

Происхождение

Количество пар кроликов образуют последовательность Фибоначчи

Последовательность Фибоначчи была хорошо известна в древней Индии[7][8][9], где она применялась в метрических науках (просодии, другими словами — стихосложении) намного раньше, чем стала известна в Европе[8][10][11].

Образец длиной n может быть построен путём добавления S к образцу длиной n − 1, либо L к образцу длиной n − 2 — и просодицисты показали, что число образцов длиною n является суммой двух предыдущих чисел в последовательности[9]. Дональд Кнут рассматривает этот эффект в книге «Искусство программирования».

На Западе эта последовательность была исследована Леонардо Пизанским, известным как Фибоначчи, в его труде «Книга абака» (1202)[12][13]. Он рассматривает развитие идеализированной (биологически нереальной) популяции кроликов, где условия таковы: изначально дана новорождённая пара кроликов (самец и самка); со второго месяца после своего рождения кролики начинают спариваться и производить новую пару кроликов, причём уже каждый месяц; кролики никогда не умирают[14][15], — а в качестве искомого выдвигает количество пар кроликов через год.

  • В начале первого месяца есть только одна новорождённая пара (1).
  • В конце первого месяца по-прежнему только одна пара кроликов, но уже спарившаяся (1).
  • В конце второго месяца первая пара рождает новую пару и опять спаривается (2).
  • В конце третьего месяца первая пара рождает ещё одну новую пару и спаривается, вторая пара только спаривается (3).
  • В конце четвёртого месяца первая пара рождает ещё одну новую пару и спаривается, вторая пара рождает новую пару и спаривается, третья пара только спаривается (5).

В конце n-го месяца количество пар кроликов будет равно количеству пар в предыдущем месяце плюс количеству новорождённых пар, которых будет столько же, сколько пар было два месяца назад, то есть {displaystyle F_{n}=F_{n-2}+F_{n-1}}[16].
Возможно, эта задача также оказалась первой, моделирующей экспоненциальный рост популяции.

Название «последовательность Фибоначчи» впервые было использовано теоретиком XIX века Эдуардом Люка[17].

Формула Бине

Формула Бине выражает в явном виде значение F_{n} как функцию от n:

F_{n}={frac {left({frac {1+{sqrt {5}}}{2}}right)^{n}-left({frac {1-{sqrt {5}}}{2}}right)^{n}}{sqrt {5}}}={frac {varphi ^{n}-(-varphi )^{-n}}{varphi -(-varphi )^{-1}}}={frac {varphi ^{n}-(-varphi )^{-n}}{2varphi -1}},

где varphi ={frac {1+{sqrt {5}}}{2}} — золотое сечение и varphi и {displaystyle (-varphi )^{-1}=1-varphi } являются корнями характеристического уравнения x^{2}-x-1=0.
Вообще, аналогичная формула существует для любой линейной рекуррентной последовательности, какой служит и последовательность Фибоначчи.

Обоснование

[18]

Преобразуем характеристическое уравнение {displaystyle x^{2}-x-1=0} к виду {displaystyle x^{2}=x+1,} умножим обе части на x: {displaystyle x^{3}=x^{2}+x} — и заменим в этой сумме x^{2} на x+1, что мы можем сделать в силу характеристического уравнения. Получим {displaystyle x^{3}=x^{2}+x=(x+1)+x=2x+1.} Затем продолжим так же умножать на x и преобразовывать x^{2}, следуя первоначальному уравнению:

{displaystyle {begin{aligned}x^{4}&=2x^{2}+x=2(x+1)+x=\&=3x+2,\x^{5}&=3x^{2}+2x=3(x+1)+2x=\&=5x+3,\x^{6}&=5x^{2}+3x=5(x+1)+3x=\&=8x+5,\x^{7}&=8x^{2}+5x=8(x+1)+5x=\&=13x+8,\&cdots end{aligned}}}

Таким образом образуется общее уравнение: {displaystyle x^{n}=F_{n}x+F_{n-1}.} Чтобы это уравнение обратить в верное равенство и отсюда выразить сами числа Фибоначчи, нужно подставить корни varphi и {displaystyle -varphi ^{-1}colon }

{displaystyle {begin{cases}varphi ^{n}=F_{n}varphi +F_{n-1},\(-varphi )^{-n}=-F_{n}varphi ^{-1}+F_{n-1},end{cases}}}

{displaystyle varphi ^{n}-(-varphi )^{-n}=F_{n}[varphi -(-varphi )^{-1}],qquad varphi ^{n}+(-varphi )^{-n}cdot varphi ^{2}=F_{n-1}(1+varphi ^{2}),}

{displaystyle color {Black}{tfrac {1}{sqrt {5}}}left(({tfrac {1+{sqrt {5}}}{2}})^{n}-({tfrac {1-{sqrt {5}}}{2}})^{n}right)=F_{n},qquad {tfrac {1}{sqrt {5}}}left(({tfrac {1+{sqrt {5}}}{2}})^{n-1}-({tfrac {1-{sqrt {5}}}{2}})^{n-1}right)=F_{n-1}.}

Следствие и обобщение

Из формулы Бине следует, что для всех ngeqslant 0 число F_{n} есть округление {displaystyle {frac {varphi ^{n}}{sqrt {5}}},} то есть {displaystyle F_{n}=leftlfloor {frac {varphi ^{n}}{sqrt {5}}}rightrceil .}
В частности, при nto infty справедлива асимптотика {displaystyle F_{n}sim {frac {varphi ^{n}}{sqrt {5}}}.}

Формула Бине может быть аналитически продолжена следующим образом:

F_{z}={frac {1}{sqrt {5}}}left(varphi ^{z}-{frac {cos {pi z}}{varphi ^{z}}}right).

При этом соотношение F_{z+2}=F_{z+1}+F_{z} выполняется для любого комплексного числа z.

Тождества

Иллюстрация формулы для суммы квадратов первых n чисел Фибоначчи[19]

  • {displaystyle F_{1}+F_{2}+F_{3}+dots +F_{n}=F_{n+2}-1.}[20]

Доказательство

Докажем формулу индукцией по n:

База индукции: {displaystyle n=0colon }

{displaystyle F_{0}=F_{2}-1=0.}

Шаг индукции: пусть утверждение для n верно:

{displaystyle F_{1}+F_{2}+F_{3}+...+F_{n}=F_{n+2}-1.}

Тогда надо доказать утверждение для {displaystyle n+1colon }

{displaystyle F_{1}+F_{2}+F_{3}+...+F_{n}+F_{n+1}=F_{n+3}-1.}

Раскладываем {displaystyle F_{n+3}} на {displaystyle F_{n+2}} и {displaystyle F_{n+1}colon }
{displaystyle F_{1}+F_{2}+F_{3}+...+F_{n}+F_{n+1}=F_{n+2}+F_{n+1}-1}
Сокращаем обе части на {displaystyle F_{n+1}colon }
{displaystyle F_{1}+F_{2}+F_{3}+...+F_{n}=F_{n+2}-1,}

что и требовалось доказать.

  • {displaystyle F_{1}+F_{3}+F_{5}+dots +F_{2n-1}=F_{2n}.}[20][21]

Доказательство

Докажем формулу индукцией по n:

База индукции: {displaystyle n=1colon }

{displaystyle F_{1}=F_{2}=1.}

Шаг индукции: Пусть утверждение для n верно:

{displaystyle F_{1}+F_{3}+F_{5}+dots +F_{2n-1}=F_{2n}.}

Тогда надо доказать утверждение для {displaystyle n+1colon }

{displaystyle F_{1}+F_{3}+F_{5}+dots +F_{2n-1}+F_{2n+1}=F_{2n+2}.}

Раскладываем {displaystyle F_{2n+2}} на {displaystyle F_{2n+1}} и {displaystyle F_{2n}colon }
{displaystyle F_{1}+F_{3}+F_{5}+dots +F_{2n-1}+F_{2n+1}=F_{2n+1}+F_{2n}.}
Сокращаем обе части на {displaystyle F_{2n+1}colon }
{displaystyle F_{1}+F_{3}+F_{5}+dots +F_{2n-1}=F_{2n}.}

что и требовалось доказать.

  • {displaystyle F_{2}+F_{4}+F_{6}+dots +F_{2n}=F_{2n+1}-1.}[20][22]
Это тождество можно доказать вычитанием первого из второго: {displaystyle {begin{alignedat}{2}(F_{1}+F_{2}+dots +F_{{color {Red}2}n})-(F_{1}+F_{3}+dots +F_{2n-1})&=F_{{color {Red}2}n+2}-1-F_{2n},\F_{2}+F_{4}+dots +F_{2n}&=F_{2n+1}-1.\end{alignedat}}}

И более общие формулы:

где матрицы имеют размер ntimes n и где i — мнимая единица.
(-1)^{n}=F_{n+1}F_{n-1}-F_{n}^{2}.
  • С равенством Кассини сопряжено более общее утверждение, названное в честь Эжена Каталана:{displaystyle F_{n}^{2}-F_{n-r}F_{n+r}=(-1)^{n-r}F_{r}^{2}.}

Свойства

Тринадцать ({displaystyle F_{7}}) способов расположения длинных (красные) и коротких слогов (серые) в каденции[en] длины шесть: пять (F_{5}) заканчивается длинным слогом и восемь ({displaystyle F_{6}}) — коротким

Последовательные наклоны плоскости и график приближений к золотому сечению, рассчитанному путём деления каждого числа Фибоначчи на предыдущее

на множестве неотрицательных целых чисел x и y[30].
  • Произведение и частное двух любых различных чисел Фибоначчи, отличных от единицы, никогда не является числом Фибоначчи.
  • Период чисел Фибоначчи по модулю натурального числа n называется периодом Пизано и обозначается pi (n). Периоды Пизано pi (n) образуют последовательность:
    1, 3, 8, 6, 20, 24, 16, 12, 24, 60, 10, 24, 28, 48, 40, 24, 36, … (последовательность A001175 в OEIS).
  • Натуральное число N является числом Фибоначчи тогда и только тогда, когда 5N^{2}+4 или 5N^{2}-4 является квадратом[31].
  • Не существует арифметической прогрессии длиной больше 3, состоящей из чисел Фибоначчи[32].
  • Число Фибоначчи F_{n+2}=F_{n+1}+F_{n} равно количеству кортежей длины n из нулей и единиц, в которых нет двух соседних единиц. При этом F_{{n+1}} равно количеству таких кортежей, начинающихся с нуля, а F_{n} — начинающихся с единицы.
  • Произведение любых n подряд идущих чисел Фибоначчи делится на произведение первых n чисел Фибоначчи.
  • Бесконечная сумма чисел, обратных числам Фибоначчи, сходится, его сумма («обратная постоянная Фибоначчи») равна 3,359884…

Вариации и обобщения

В других областях

Жёлтая ромашковая головка, показывающая расположение в 21 (синяя) и 13 (аква) спиралей. Такие схемы, включающие последовательные числа Фибоначчи, встречаются у самых разных растений

Число возможных предков на линии наследования Х-хромосомы в данном поколении предков следует последовательности Фибоначчи (Хатчисон Л. Растущее семейное древо: сила ДНК в восстановлении семейных отношений)[33]

Иллюстрация модели Фогеля для n = 1 … 500

Существует мнение, что почти все утверждения, находящие числа Фибоначчи в природных и исторических явлениях, неверны — это распространённый миф, который часто оказывается неточной подгонкой под желаемый результат[34][35].

В природе

  • Филлотаксис (листорасположение) у растений описывается последовательностью Фибоначчи, если листья (почки) на однолетнем приросте (побеге, стебле) имеют так называемое спиральное листорасположение. При этом число последовательно расположенных листьев (почек) по спирали плюс один, а также число совершенных при этом полных оборотов спирали вокруг оси однолетнего прироста (побега, стебля) выражаются обычно первыми числами Фибоначчи.
  • Семена подсолнуха, сосновые шишки, лепестки цветков, ячейки ананаса также располагаются согласно последовательности Фибоначчи[36][37][38][39].

В искусстве

В поэзии чаще находят отношение «золотого сечения» (золотую пропорцию), связанное через формулу Бине с числами Фибоначчи. Например, в поэме Ш. Руставели «Витязь в тигровой шкуре» и на картинах художников[40].

Однако числа Фибоначчи встречаются и непосредственно в поэзии и в музыке[41]

В кодировании

В теории кодирования предложены устойчивые так называемые «коды Фибоначчи»[42], причём основание этих кодов — иррациональное число.

См. также

  • Дерево Фибоначчи
  • Метод Фибоначчи с запаздываниями
  • Метод Фибоначчи поиска экстремума
  • Фибоначчи
  • Фибоначчиева система счисления
  • Числа Бине
  • Числа Леонардо
  • Таблица Витхоффа
  • Последовательность коров Нараяны
  • Золотое сечение
  • Пропорционирование

Примечания

  1. John Hudson Tiner. Изучение мира математики: от древних записей до новейших достижений в области компьютеров. — New Leaf Publishing Group, 200. — ISBN 978-1-61458-155-0.
  2. См., например, Т. В. Кропотова, В. Г. Подольский, П. Е. Кашаргин. Введение в высшую математику. — Казанский федеральный университет институт физики.
  3. Lucas, 1891, p. 3.
  4. Числа Фибоначчи // Большая советская энциклопедия : [в 30 т.] / гл. ред. А. М. Прохоров. — 3-е изд. — М. : Советская энциклопедия, 1969—1978.
  5. Beck & Geoghegan (2010).
  6. Bóna, 2011, p. 180.
  7. Goonatilake, Susantha (1998), Toward a Global Science, Indiana University Press, с. 126, ISBN 978-0-253-33388-9, <https://books.google.com/books?id=SI5ip95BbgEC&pg=PA126>
  8. 1 2 Singh, Parmanand (1985), The So-called Fibonacci numbers in ancient and medieval India, Historia Mathematica Т. 12 (3): 229—244, DOI 10.1016/0315-0860(85)90021-7
  9. 1 2 Knuth, Donald (2006), The Art of Computer Programming, vol. 4. Generating All Trees – History of Combinatorial Generation, Addison–Wesley, с. 50, ISBN 978-0-321-33570-8, <https://books.google.com/books?id=56LNfE2QGtYC&pg=PA50&dq=rhythms>
  10. Knuth, Donald (1968), The Art of Computer Programming, vol. 1, Addison Wesley, с. 100, ISBN 978-81-7758-754-8, <https://books.google.com/books?id=MooMkK6ERuYC&pg=PA100>
  11. Livio, 2003, p. 197.
  12. Pisano, 2002, pp. 404—405.
  13. Fibonacci’s Liber Abaci (Book of Calculation). The University of Utah (13 декабря 2009). Дата обращения: 28 ноября 2018.
  14. Hemenway, Priya. Divine Proportion: Phi In Art, Nature, and Science (англ.). — New York: Sterling, 2005. — P. 20—21. — ISBN 1-4027-3522-7.
  15. Knott, Dr. Ron The Fibonacci Numbers and Golden section in Nature – 1. University of Surrey (25 сентября 2016). Дата обращения: 27 ноября 2018.
  16. Knott, Ron Fibonacci’s Rabbits. University of Surrey Faculty of Engineering and Physical Sciences.
  17. Gardner, Martin (1996), Mathematical Circus, The Mathematical Association of America, с. 153, ISBN 978-0-88385-506-5
  18. Art of Problem Solving. artofproblemsolving.com. Дата обращения: 9 мая 2021.
  19. Фибоначчи числа // Энциклопедический словарь юного математика / Сост. Савин А. П.. — 2-е изд. — М.: Педагогика, 1989. — С. 312—314. — 352 с. — ISBN 5715502187.
  20. 1 2 3 4 5 Теорема изложена в данном файле.
  21. Пункт 23.
  22. Пункт 24.
  23. Следствие из пункта 36.
  24. Пункт 30.
  25. 64.
  26. Пункт 55.
  27. proof of Cassini’s identity. planetmath.org. Дата обращения: 30 мая 2021.
  28. Тождество Кассини.
  29. J H E Cohn. Square Fibonacci Numbers Etc, С. 109—113. Архивировано 11 июля 2010 года. Дата обращения: 1 июля 2010.
  30. P. Ribenboim. The New Book of Prime Number Records. — Springer, 1996. — С. 193.
  31. Ira Gessel. Problem H-187 // Fibonacci Quarterly. — 1972. — Т. 10. — С. 417—419.
  32. В. Серпинский. Задача 66 // 250 задач по элементарной теории чисел. — М.: Просвещение, 1968. — 168 с.
  33. Hutchison, Luke. Growing the Family Tree: The Power of DNA in Reconstructing Family Relationships (англ.) // Proceedings of the First Symposium on Bioinformatics and Biotechnology (BIOT-04) : journal. — 2004. — September.
  34. Fibonacci Flim-Flam. Архивная копия от 23 апреля 2012 на Wayback Machine (англ.).
  35. The Myth That Will Not Go Away (англ.).
  36. Золотое сечение в природе.
  37. Числа Фибоначчи.
  38. Числа Фибоначчи.
  39. Акимов О. Е. Конец науки.
  40. Волошинов А. В. Математика и искусство. Москва: Просвещение, 2000. 400 с. ISBN 5-09-008033-X
  41. Математика в стихах и музыке
  42. Стахов А., Слученкова А., Щербаков И. Код да Винчи и ряды Фибоначчи. СПБ. Издательство: Питер, 2006. 320 с. ISBN 5-469-01369-3

Литература

  • Н. Н. Воробьёв. Числа Фибоначчи. — Наука, 1978. — Т. 39. — (Популярные лекции по математике).
  • А. И. Маркушевич. Возвратные последовательности. — Гос. Издательство Технико-Теоретической Литературы, 1950. — Т. 1. — (Популярные лекции по математике).
  • А. Н. Рудаков. Числа Фибоначчи и простота числа 2127 − 1 // Математическое Просвещение, третья серия. — 2000. — Т. 4.
  • Дональд Кнут. Искусство программирования, том 1. Основные алгоритмы = The Art of Computer Programming, vol. 1. Fundamental Algorithms. — 3-е изд. — М.: «Вильямс», 2006. — С. 720. — ISBN 0-201-89683-4.
  • Дональд Кнут, Роналд Грэхем, Орен Паташник. Конкретная математика. Основание информатики = Concrete Mathematics. A Foundation for Computer Science. — М.: Мир; Бином. Лаборатория знаний, 2006. — С. 703. — ISBN 5-94774-560-7.
  • Грант Аракелян. Математика и история золотого сечения. — М.: Логос, 2014. — 404 с. — ISBN 978-5-98704-663-0.
  • Ball, Keith M (2003), 8: Fibonacci’s Rabbits Revisited, Strange Curves, Counting Rabbits, and Other Mathematical Explorations, Princeton, NJ: Princeton University Press, ISBN 978-0-691-11321-0.
  • Beck, Matthias & Geoghegan, Ross (2010), The Art of Proof: Basic Training for Deeper Mathematics, New York: Springer, ISBN 978-1-4419-7022-0.
  • Bóna, Miklós (2011), A Walk Through Combinatorics (3rd ed.), New Jersey: World Scientific, ISBN 978-981-4335-23-2.
    • Bóna, Miklós (2016), A Walk Through Combinatorics (4th Revised ed.), New Jersey: World Scientific, ISBN 978-981-3148-84-0.
  • Lemmermeyer, Franz (2000), Reciprocity Laws: From Euler to Eisenstein, Springer Monographs in Mathematics, New York: Springer, ISBN 978-3-540-66957-9.
  • Livio, Mario. The Golden Ratio: The Story of Phi, the World’s Most Astonishing Number (англ.). — First trade paperback. — New York City: Broadway Books  (англ.) (рус., 2003. — ISBN 0-7679-0816-3.
  • Lucas, Édouard (1891), Théorie des nombres, vol. 1, Paris: Gauthier-Villars, Théorie des nombres в «Книгах Google», <https://archive.org/details/thoriedesnombr01lucauoft>.
  • Pisano, Leonardo (2002), Fibonacci’s Liber Abaci: A Translation into Modern English of the Book of Calculation, Sources and Studies in the History of Mathematics and Physical Sciences, Springer, ISBN 978-0-387-95419-6

Ссылки

  • Первые 300 чисел Фибоначчи (англ.).
  • Числа Фибоначчи в природе (англ.).

Задача: посчитать N-е число последовательности, в которой каждый элемент равен сумме двух предыдущих. Такая последовательность называется последовательностью Фибоначчи: 1, 1, 2, 3, 5, 8…

Очень часто на разнообразных олимпиадах попадаются задачи вроде этой, которые, как думается на первый взгляд, можно решить с помощью простого перебора. Но если мы подсчитаем количество возможных вариантов, то сразу убедимся в неэффективности такого подхода: например, простая рекурсивная функция, приведенная ниже, будет потреблять существенные ресурсы уже на 30-ом числе Фибоначчи, тогда как на олимпиадах время решения часто ограничено 1-5 секундами.

int fibo(int n)
{
    if (n == 1 || n == 2) {
        return 1;
    } else {
        return fibo(n - 1) + fibo(n - 2);
    }
}

Давайте подумаем, почему так происходит. Например, для вычисления fibo(30) мы сначала вычисляем fibo(29) и fibo(28). Но при этом наша программа «забывает», что fibo(28) мы уже вычисляли при поиске fibo(29).

Основная ошибка такого подхода «в лоб» в том, что одинаковые значения аргументов функции исчисляются многократно — а ведь это достаточно ресурсоемкие операции. Избавиться от повторяющихся вычислений нам поможет метод динамического программирования — это прием, при использовании которого задача разбивается на общие и повторяющиеся подзадачи, каждая из которых решается только 1 раз — это значительно повышает эффективность программы. Этот метод подробно описан в нашей статье, там же есть и примеры решения других задач.

Самый просто вариант улучшения нашей функции — запоминать, какие значения мы уже вычисляли. Для этого нужно ввести дополнительный массив, который будет служить как бы «кэшем» для наших вычислений: перед вычислением нового значения мы будем проверять, не вычисляли ли его раньше. Если вычисляли, то будем брать из массива готовое значение, а если не вычисляли — придётся считать его на основе предыдущих и запоминать на будущее:

int cache[100];

int fibo(int n)
{
    if (cache[n] == 0) {
        if (n == 1 || n == 2) {
            cache[n] = 1;
        } else {
            cache[n] = fibo(n - 1) + fibo(n - 2);
        }
    }

    return cache[n];
}

Так как в данной задаче для вычисления N-ого значения нам гарантированно понадобится (N-1)-е, то не составит труда переписать формулу в итерационный вид — просто будем заполнять наш массив подряд до тех пор, пока не дойдём до нужной ячейки:

cache[0] = 1;
cache[1] = 1;

for (int i = 2; i <= n; i++) {
    cache[i] = cache[i - 1] + cache[i - 2];
}

cout << cache[n-1];

Теперь мы можем заметить, что когда мы вычисляем значение F(N), то значение F(N-3) нам уже гарантированно никогда не понадобится. То есть нам достаточно хранить в памяти лишь два значения — F(N-1) и F(N-2). Причём, как только мы вычислили F(N), хранение F(N-2) теряет всякий смысл. Попробуем записать эти размышления в виде кода:

//Два предыдущих значения:
int cache1 = 1;
int cache2 = 1;
//Новое значение
int cache3;

for (int i = 2; i <= n; i++) {
    cache3 = cache1 + cache2; //Вычисляем новое значение

    //Абстрактный cache4 будет равен cache3+cache2
    //Значит cache1 нам уже не нужен?..

    //Отлично, значит cache1 -- то значение, которое потеряет актуальность на следующей итерации.
    //cache5 = cache4 - cache3 => через итерацию потеряет актуальность cache2, т.е. он и должен стать cache1

    //Иными словами, cache1 -- f(n-2), cache2 -- f(n-1), cache3 -- f(n).
    //Пусть N=n+1 (номер, который мы вычисляем на следующей итерации). Тогда n-2=N-3, n-1=N-2, n=N-1.
    //В соответствии с новыми реалиями мы и переписываем значения наших переменных:

    cache1 = cache2;
    cache2 = cache3;
}

cout << cache3;

Бывалому программисту понятно, что код выше, в общем-то ерунда, так как cache3 никогда не используется (он сразу записывается в cache2), и всю итерацию можно переписать, используя всего одно выражение:

cache[0] = 1;
cache[1] = 1;
 
for (int i = 2; i <= n; i++) {
    cache[i%2] = cache[0] + cache[1];
    //При i=2 устареет 0-й элемент
    //При i=3 в 0 будет свежий элемент (обновили его на предыдущей итерации), а в 1 -- ещё старый
    //При i=4 последним элементом мы обновляли cache[1], значит ненужное старьё сейчас в cache[0]
    //Интуитивно понятно, что так будет продолжаться и дальше
}
 
cout << cache[n%2];

Для тех, кто не может понять, как работает магия с остатком от деления, или просто хочет увидеть более неочевидную формулу, существует ещё одно решение:

int x = 1;
int y = 1;

for (int i = 2; i < n; i++) {
   y = x + y;
   x = y - x;
}

cout << "Число Фибоначчи: " << y;

Попробуйте проследить за выполнением этой программы: вы убедитесь в правильности алгоритма.


P.S. Вообще, существует единая формула для вычисления любого числа Фибоначчи, которая не требует никаких итераций или рекурсии:

const double SQRT5 = sqrt(5);
const double PHI = (SQRT5 + 1) / 2;

int fibo(int n){
    return int(pow(PHI, n) / SQRT5 + 0.5);
}

Но, как можете догадаться, подвох в том, что цена вычисления степеней нецелых чисел довольно велика, как и их погрешность.


Загрузить PDF


Загрузить PDF

Последовательность Фибоначчи – это ряд чисел, в котором каждое последующее число равно сумме двух предыдущих чисел. Числовые последовательности часто встречаются в природе и искусстве в виде спиралей и «золотого сечения». Самый простой способ вычислить последовательность Фибоначчи – это создать таблицу, но такой метод не применим к большим последовательностям. Например, если нужно определить 100-й член последовательности, лучше воспользоваться формулой Бине.

  1. Изображение с названием Calculate the Fibonacci Sequence Step 1

    1

    Нарисуйте таблицу с двумя столбцами. Количество строк таблицы зависит от количества чисел последовательности Фибоначчи, которые нужно найти.

    • Например, если нужно найти пятое число последовательности, нарисуйте таблицу с пятью строками.
    • Используя таблицу, нельзя найти некоторое случайное число без вычисления всех предыдущих чисел. Например, если нужно найти 100-е число последовательности, нужно вычислить все числа: от первого до 99-ого. Поэтому таблица применима только для нахождения первых чисел последовательности.
  2. Изображение с названием Calculate the Fibonacci Sequence Step 2

    2

    В левом столбце напишите порядковые номера членов последовательности. То есть напишите цифры по порядку, начиная с единицы.

    • Такие цифры определяют порядковые номера членов (чисел) последовательности Фибоначчи.
    • Например, если нужно найти пятое число последовательности, в левой колонке напишите следующие цифры: 1, 2, 3, 4, 5. То есть нужно найти с первого по пятое число последовательности.
  3. Изображение с названием Calculate the Fibonacci Sequence Step 3

    3

    В первой строке правой колонки напишите 1. Это первое число (член) последовательности Фибоначчи.

    • Имейте в виду, что последовательность Фибоначчи всегда начинается с 1. Если последовательность начинается с другого числа, вы неправильно вычислили все числа вплоть до первого.
  4. Изображение с названием Calculate the Fibonacci Sequence Step 4

    4

    К первому члену (1) прибавьте 0. Получится второе число последовательности.

    • Запомните: чтобы найти любое число последовательности Фибоначчи, просто сложите два предыдущих числа.
    • Чтобы создать последовательность, не забудьте о 0, который стоит перед 1 (первым членом), поэтому 1 + 0 = 1.
  5. Изображение с названием Calculate the Fibonacci Sequence Step 5

    5

    Сложите первый (1) и второй (1) члены. Получится третье число последовательности.

    • 1 + 1 = 2. Третий член равен 2.
  6. Изображение с названием Calculate the Fibonacci Sequence Step 6

    6

    Сложите второй (1) и третий (2) члены, чтобы получить четвертое число последовательности.

    • 1 + 2 = 3. Четвертый член равен 3.
  7. Изображение с названием Calculate the Fibonacci Sequence Step 7

    7

    Сложите третий (2) и четвертый (3) члены. Получится пятое число последовательности.

    • 2 + 3 = 5. Пятый член равен 5.
  8. Изображение с названием Calculate the Fibonacci Sequence Step 8

    8

    Сложите два предыдущих числа, чтобы найти любое число последовательности Фибоначчи. Этот метод основан на формуле: F_{{n}}=F_{{n-1}}+F_{{n-2}}.[1]
    Эта формула не является замкнутой, поэтому при помощи этой формулы нельзя найти любой член последовательности без вычисления всех предыдущих чисел.

    Реклама

  1. Изображение с названием Calculate the Fibonacci Sequence Step 9

    1

  2. Изображение с названием Calculate the Fibonacci Sequence Step 10

    2

    В формулу подставьте порядковый номер числа (вместо n). n – это порядковый номер любого искомого члена последовательности.

  3. Изображение с названием Calculate the Fibonacci Sequence Step 11

    3

    В формулу подставьте золотое сечение. Золотое сечение приблизительно равно 1,618034; подставьте в формулу это число.[5]

  4. Изображение с названием Calculate the Fibonacci Sequence Step 12

    4

    Вычислите выражение в скобках. Не забывайте про правильный порядок выполнения математических операций, в котором выражение в скобках вычисляется в первую очередь:1-1,618034=-0,618034.

  5. Изображение с названием Calculate the Fibonacci Sequence Step 13

    5

    Возведите числа в степени. Возведите в соответствующие степени два числа, которые находятся в числителе.

  6. Изображение с названием Calculate the Fibonacci Sequence Step 14

    6

    Вычтите два числа. Перед тем как приступить к делению, вычтите числа, которые находятся в числителе.

  7. Изображение с названием Calculate the Fibonacci Sequence Step 15

    7

    Полученный результат разделите на квадратный корень из 5. Квадратный корень из 5 приблизительно равен 2,236067.

    • В нашем примере: {frac  {11,180339}{2,236067}}=5,000002.
  8. Изображение с названием Calculate the Fibonacci Sequence Step 16

    8

    Полученный результат округлите до ближайшего целого числа. Последний результат будет десятичной дробью, которая близка к целому числу. Такое целое число представляет собой число последовательности Фибоначчи.

    • Если в вычислениях использовать неокругленные числа, вы получите целое число. Работать с округленными числами намного легче, но в этом случае вы получите десятичную дробь.[6]
    • В нашем примере вы получили десятичную дробь 5,000002. Округлите ее до ближайшего целого числа и получите пятое число последовательности Фибоначчи, которое равно 5.

    Реклама

Об этой статье

Эту страницу просматривали 27 660 раз.

Была ли эта статья полезной?


Download Article


Download Article

The Fibonacci sequence is a pattern of numbers generated by summing the previous two numbers in the sequence.[1]
The numbers in the sequence are frequently seen in nature and in art, represented by spirals and the golden ratio. The easiest way to calculate the sequence is by setting up a table; however, this is impractical if you are looking for, for example, the 100th term in the sequence, in which case Binet’s formula can be used.

  1. Image titled Calculate the Fibonacci Sequence Step 1

    1

    Set up a table with two columns. The number of rows will depend on how many numbers in the Fibonacci sequence you want to calculate.[2]

    • For example, if you want to find the fifth number in the sequence, your table will have five rows.
    • When using the table method, you cannot find a random number farther down in the sequence without calculating all the number before it. For example, if you want to find the 100th number in the sequence, you have to calculate the 1st through 99th numbers first. This is why the table method only works well for numbers early in the sequence.
  2. Image titled Calculate the Fibonacci Sequence Step 2

    2

    Enter the sequence of terms in the left column. This means just entering a sequence of sequential ordinal numbers, beginning with “1st.”

    • The term refers to the position number in the Fibonacci sequence.
    • For example, if you want to figure out the fifth number in the sequence, you will write 1st, 2nd, 3rd, 4th, 5th down the left column. This will show you what the first through fifth terms in the sequence are.

    Advertisement

  3. Image titled Calculate the Fibonacci Sequence Step 3

    3

    Enter 1 in the first row of the right-hand column. This is the starting point for the Fibonacci Sequence. In other words, the first term in the sequence is 1.

    • The correct Fibonacci sequence always starts on 1. If you begin with a different number, you are not finding the proper pattern of the Fibonacci sequence.
  4. Image titled Calculate the Fibonacci Sequence Step 4

    4

    Add the first term (1) and 0. This will give you the second number in the sequence.

    • Remember, to find any given number in the Fibonacci sequence, you simply add the two previous numbers in the sequence.
    • To create the sequence, you should think of 0 coming before 1 (the first term), so 1 + 0 = 1.
  5. Image titled Calculate the Fibonacci Sequence Step 5

    5

    Add the first term (1) and the second term (1). This will give you the third number in the sequence.[3]

    • 1 + 1 = 2. The third term is 2.
  6. Image titled Calculate the Fibonacci Sequence Step 6

    6

    Add the second term (1) and the third term (2) to get the fourth number in the sequence.

    • 1 + 2 = 3. The fourth term is 3.
  7. Image titled Calculate the Fibonacci Sequence Step 7

    7

    Add the third term (2) and the fourth term (3). This will give you the fifth number in the sequence.[4]

    • 2 + 3 = 5. The fifth term is 5.
  8. Image titled Calculate the Fibonacci Sequence Step 8

    8

    Sum the previous two numbers to find any given number in the Fibonacci Sequence. When you use this method, you are using the formula F_{{n}}=F_{{n-1}}+F_{{n-2}}.[5]
    Since this is not a closed formula, however, you cannot use it to calculate any given term in the sequence without calculating all the previous numbers.[6]

  9. Advertisement

  1. Image titled Calculate the Fibonacci Sequence Step 9

    1

  2. Image titled Calculate the Fibonacci Sequence Step 10

    2

    Plug the number for n into the formula. The n represents whatever term you are looking for in the sequence.

  3. Image titled Calculate the Fibonacci Sequence Step 11

    3

    Substitute the golden ratio into the formula. You can use 1.618034 as an approximation of the golden ratio.[10]

  4. Image titled Calculate the Fibonacci Sequence Step 12

    4

    Complete the calculations in parentheses. Remember to use the order of operations by completing the calculation in parentheses first: 1-1.618034=-0.618034.

  5. Image titled Calculate the Fibonacci Sequence Step 13

    5

    Calculate the exponents. Multiply the two parenthetical numbers in the numerator by the appropriate exponent.

  6. Image titled Calculate the Fibonacci Sequence Step 14

    6

    Complete the subtraction. Before you divide, you need to subtract the two numbers in the numerator.

  7. Image titled Calculate the Fibonacci Sequence Step 15

    7

    Divide by the square root of 5. The square root of 5, rounded, is 2.236067.[11]

    • In the example problem, {frac  {11.180339}{2.236067}}=5.000002.
  8. Image titled Calculate the Fibonacci Sequence Step 16

    8

    Round to the nearest whole number. Your answer will be a decimal, but it will be very close to a whole number. This whole number represents the number in the Fibonacci sequence.

    • If you used the complete golden ratio and did no rounding, you would get a whole number. It’s more practical to round, however, which will result in a decimal.[12]
    • In the example, after using a calculator to complete all the calculations, your answer will be approximately 5.000002. Rounding to the nearest whole number, your answer, representing the fifth number in the Fibonacci sequence, is 5.
  9. Advertisement

Add New Question

  • Question

    Is “Fibonacci” an English word?

    Danoyachtcapt

    Danoyachtcapt

    Top Answerer

    No, it is the name of mathematician Leonardo of Pisa.

  • Question

    How do I deduce Binet’s fibonacci number formula?

    Orangejews

    Orangejews

    Community Answer

    One way is to interpret the recursion as a matrix multiplication. Take a vector of two consecutive terms like (13, 8), multiply by a transition matrix M = (1,1; 1,0) to get the next such vector (21,13). That gives a formula involving M^n, but if you diagonalize M, computing M^n is easy and that formula pops right out.

  • Question

    Who discovered this sequence?

    WOOHP

    Leonardo Bonacci

See more answers

Ask a Question

200 characters left

Include your email address to get a message when this question is answered.

Submit

Advertisement

Video

Thanks for submitting a tip for review!

References

About This Article

Article SummaryX

To calculate the Fibonacci sequence up to the 5th term, start by setting up a table with 2 columns and writing in 1st, 2nd, 3rd, 4th, and 5th in the left column. Next, enter 1 in the first row of the right-hand column, then add 1 and 0 to get 1. Write 1 in the column next to “2nd,” then add the 1st and 2nd term to get 2, which is the 3rd number in the sequence. Continue this pattern of adding the 2 previous numbers in the sequence to get 3 for the 4th term and 5 for the 5th term. To learn more, including how to calculate the Fibonacci sequence using Binet’s formula and the golden ratio, scroll down.

Did this summary help you?

Thanks to all authors for creating a page that has been read 246,239 times.

Did this article help you?

Время на прочтение
5 мин

Количество просмотров 306K

Введение

Программистам числа Фибоначчи должны уже поднадоесть. Примеры их вычисления используются везде. Всё от того, что эти числа предоставляют простейший пример рекурсии. А ещё они являются хорошим примером динамического программирования. Но надо ли вычислять их так в реальном проекте? Не надо. Ни рекурсия, ни динамическое программирование не являются идеальными вариантами. И не замкнутая формула, использующая числа с плавающей запятой. Сейчас я расскажу, как правильно. Но сначала пройдёмся по всем известным вариантам решения.

Код предназначен для Python 3, хотя должен идти и на Python 2.

Для начала – напомню определение:

Fn= Fn-1+ Fn-2

и F1= F2=1.

Замкнутая формула

Пропустим детали, но желающие могут ознакомиться с выводом формулы. Идея в том, чтобы предположить, что есть некий x, для которого Fn = xn, а затем найти x.

что означает

сокращаем xn-2

Решаем квадратное уравнение:

Откуда и растёт «золотое сечение» ϕ=(1+√5)/2. Подставив исходные значения и проделав ещё вычисления, мы получаем:

что и используем для вычисления Fn.

from __future__ import division
import math

def fib(n):
    SQRT5 = math.sqrt(5)
    PHI = (SQRT5 + 1) / 2
    return int(PHI ** n / SQRT5 + 0.5)

Хорошее:
Быстро и просто для малых n
Плохое:
Требуются операции с плавающей запятой. Для больших n потребуется большая точность.
Злое:
Использование комплексных чисел для вычисления Fn красиво с математической точки зрения, но уродливо — с компьютерной.

Рекурсия

Самое очевидное решение, которое вы уже много раз видели – скорее всего, в качестве примера того, что такое рекурсия. Повторю его ещё раз, для полноты. В Python её можно записать в одну строку:

fib = lambda n: fib(n - 1) + fib(n - 2) if n > 2 else 1

Хорошее:
Очень простая реализация, повторяющая математическое определение
Плохое:
Экспоненциальное время выполнения. Для больших n очень медленно
Злое:
Переполнение стека

Запоминание

У решения с рекурсией есть большая проблема: пересекающиеся вычисления. Когда вызывается fib(n), то подсчитываются fib(n-1) и fib(n-2). Но когда считается fib(n-1), она снова независимо подсчитает fib(n-2) – то есть, fib(n-2) подсчитается дважды. Если продолжить рассуждения, будет видно, что fib(n-3) будет подсчитана трижды, и т.д. Слишком много пересечений.

Поэтому надо просто запоминать результаты, чтобы не подсчитывать их снова. Время и память у этого решения расходуются линейным образом. В решении я использую словарь, но можно было бы использовать и простой массив.

M = {0: 0, 1: 1}

def fib(n):
    if n in M:
        return M[n]
    M[n] = fib(n - 1) + fib(n - 2)
    return M[n]

(В Python это можно также сделать при помощи декоратора, functools.lru_cache.)

Хорошее:
Просто превратить рекурсию в решение с запоминанием. Превращает экспоненциальное время выполнение в линейное, для чего тратит больше памяти.
Плохое:
Тратит много памяти
Злое:
Возможно переполнение стека, как и у рекурсии

Динамическое программирование

После решения с запоминанием становится понятно, что нам нужны не все предыдущие результаты, а только два последних. Кроме этого, вместо того, чтобы начинать с fib(n) и идти назад, можно начать с fib(0) и идти вперёд. У следующего кода линейное время выполнение, а использование памяти – фиксированное. На практике скорость решения будет ещё выше, поскольку тут отсутствуют рекурсивные вызовы функций и связанная с этим работа. И код выглядит проще.

Это решение часто приводится в качестве примера динамического программирования.

def fib(n):
    a = 0
    b = 1
    for __ in range(n):
        a, b = b, a + b
    return a

Хорошее:
Быстро работает для малых n, простой код
Плохое:
Всё ещё линейное время выполнения
Злое:
Да особо ничего.

Матричная алгебра

И, наконец, наименее освещаемое, но наиболее правильное решение, грамотно использующее как время, так и память. Его также можно расширить на любую гомогенную линейную последовательность. Идея в использовании матриц. Достаточно просто видеть, что

А обобщение этого говорит о том, что

Два значения для x, полученных нами ранее, из которых одно представляло собою золотое сечение, являются собственными значениями матрицы. Поэтому, ещё одним способом вывода замкнутой формулы является использование матричного уравнения и линейной алгебры.

Так чем же полезна такая формулировка? Тем, что возведение в степень можно произвести за логарифмическое время. Это делается через возведения в квадрат. Суть в том, что

где первое выражение используется для чётных A, второе для нечётных. Осталось только организовать перемножения матриц, и всё готово. Получается следующий код. Я организовал рекурсивную реализацию pow, поскольку её проще понять. Итеративную версию смотрите тут.

def pow(x, n, I, mult):
    """
    Возвращает x в степени n. Предполагает, что I – это единичная матрица, которая 
    перемножается с mult, а n – положительное целое
    """
    if n == 0:
        return I
    elif n == 1:
        return x
    else:
        y = pow(x, n // 2, I, mult)
        y = mult(y, y)
        if n % 2:
            y = mult(x, y)
        return y


def identity_matrix(n):
    """Возвращает единичную матрицу n на n"""
    r = list(range(n))
    return [[1 if i == j else 0 for i in r] for j in r]


def matrix_multiply(A, B):
    BT = list(zip(*B))
    return [[sum(a * b
                 for a, b in zip(row_a, col_b))
            for col_b in BT]
            for row_a in A]


def fib(n):
    F = pow([[1, 1], [1, 0]], n, identity_matrix(2), matrix_multiply)
    return F[0][1]

Хорошее:
Фиксированный объём памяти, логарифмическое время
Плохое:
Код посложнее
Злое:
Приходится работать с матрицами, хотя они не так уж и плохи

Сравнение быстродействия

Сравнивать стоит только вариант динамического программирования и матрицы. Если сравнивать их по количеству знаков в числе n, то получится, что матричное решение линейно, а решение с динамическим программированием – экспоненциально. Практический пример – вычисление fib(10 ** 6), числа, у которого будет больше двухсот тысяч знаков.

n = 10 ** 6
Вычисляем fib_matrix: у fib(n) всего 208988 цифр, расчёт занял 0.24993 секунд.
Вычисляем fib_dynamic: у fib(n) всего 208988 цифр, расчёт занял 11.83377 секунд.


Теоретические замечания

Не напрямую касаясь приведённого выше кода, данное замечание всё-таки имеет определённый интерес. Рассмотрим следующий граф:

image

Подсчитаем количество путей длины n от A до B. Например, для n = 1 у нас есть один путь, 1. Для n = 2 у нас опять есть один путь, 01. Для n = 3 у нас есть два пути, 001 и 101. Довольно просто можно показать, что количество путей длины n от А до В равно в точности Fn. Записав матрицу смежности для графа, мы получим такую же матрицу, которая была описана выше. Это известный результат из теории графов, что при заданной матрице смежности А, вхождения в Аn — это количество путей длины n в графе (одна из задач, упоминавшихся в фильме «Умница Уилл Хантинг»).

Почему на рёбрах стоят такие обозначения? Оказывается, что при рассмотрении бесконечной последовательности символов на бесконечной в обе стороны последовательности путей на графе, вы получите нечто под названием “подсдвиги конечного типа”, представляющее собой тип системы символической динамики. Конкретно этот подсдвиг конечного типа известен, как «сдвиг золотого сечения», и задаётся набором «запрещённых слов» {11}. Иными словами, мы получим бесконечные в обе стороны двоичные последовательности и никакие пары из них не будут смежными. Топологическая энтропия этой динамической системы равна золотому сечению ϕ. Интересно, как это число периодически появляется в разных областях математики.

Добавить комментарий