外国為替市場

整数の公式でフィボナッチ数列を求める

整数の公式でフィボナッチ数列を求める
ただし、\(F_1=F_2=1\)とします。これは漸化式といって、前の番号の数の情報によって新たな数が構成されていく仕組みになっています。こうして得られる数列をフィボナッチ数列、そしてフィボナッチ数列に現れる数をフィボナッチ数と呼びます。
フィボナッチ数は前2つの数を足すことによって構成していきます。例えば、1番目と2番目は\(1\)であることから3番目は\(1+1=2\)。4番目は\(1+2=3\)、5番目は\(2+3=5\)となります。最初のいくつかのフィボナッチ数を求めてみましょう。

フィボナッチ数列の一般項を計算する(※ただし有理数に限る)

さて、この FibNum こと Rational の二要素からなるタプルは、左に \( \sqrt \) が付かない項を、右に \( \sqrt \) が付く項を格納することしよう。つまり (1, 1) と書けば \( 1 + \sqrt \) のこと。 (0, 1) と書けば \( \sqrt \) のこと。 (1 % 2, 1 % 3) と書けば \( \frac + \frac \sqrt \) のことを表す。

式を書き下す

OK。さすがにちょっと見づらいがまあ仕方ない。でも fibDiv として素直に除算を除算のまま書き下してしまった。除算は \( 0 整数の公式でフィボナッチ数列を求める 整数の公式でフィボナッチ数列を求める \) で割れないとか面倒なこともあるので、乗算の形にしておきたい。

まず、 (1, 1) `fibDiv` (2, 0) は要するに \( \frac> \) のことだが、こんなものは \( \frac + \frac\sqrt \)、つまり (1 % 2, 1 % 2) としてしまえば良い。

後ろ側の \( \sqrt \) で割る処理は、逆数であるところの \( \frac<\sqrt> \) 、つまり \( \frac<\sqrt> \) を掛ければ良い。\( \frac<\sqrt> \) ってことは \( 0 + \frac\sqrt \) だから、ここでの表現では (0, 1 % 5) ってことだ。

演算子を実装する : 累乗

\( n \) が大きいとそのまま \(n – 1\) 回の乗算をすることになってちょっとばかり遅い。二乗の結果が使えるところはどんどんそれを使って計算させることにしよう。乗算の回数が最大でも \( 2 \log \) 回で済む。

演算子を実装する : 乗算

FibNum の乗算とは何かと言うと、\( (a + b\sqrt)(c + d\sqrt) \) ってことで、つまり、

\begin & & (a + b\sqrt)(c + d\sqrt) \\ &=& ac + ad\sqrt + bc\sqrt + 5bd \\ &=& (ac + 5bd) + (ad + bc)\sqrt \end

フィボナッチ数列

例えば「3, 6, 12, 24, 整数の公式でフィボナッチ数列を求める 48. 」の数列で考えていきましょう。初項は3、公比は2です。
一般項、つまりn番目の項は「初項3に公比2をn-1回かけた数」なので
$a_ = 3 \times 2^$ となります。
$n=2$ の時、$3 \times 2^=3 \times 2 = 6$
$n=3$ の時、$3 \times 2^=3 \times 4 = 12$
$n=4$ の時、$3 \times 2^=3 \times 8 = 24$
これを一般化すると、初項 $a$、公比 $r$ の等比数列における一般項は
$a_ = a \times r^$ となります。

フィボナッチ数の等比数列

等比数列の一般項は、$a_ = ar^$ ですから、次項は $a_ = ar^$、次の次項 $a_ = ar^$ です。

これを二次方程式に変形すると
$r^-r-1 = 0$

二次方程式の解の公式に当てはめる

ただ、これだけだと先頭の $1$ と $1$ が満たせないので、もう一工夫必要です。
解の公式により解が2つ求まったので、$α$ と $β$ にして、$α-β$ とすると $\sqrt$ がそれぞれに付きます。あとは、$\sqrt$ で割ればフィボナッチ数列が求まります。
詳しく下記を参照してください。

Fibonacci.png

普通に実装

※ np.sqrt を使わないでPythonの基本機能で実現する場合、5**0.5 で平方根の演算ができます。

100 番目の本当のフィボナッチ数は $354224848179261915075$ です。
残念ながら値が違ってしまいますね。
$354224848179263111168$
$354224848179261915075$

たかが 100 番目くらいで正しい答えを得られないようでは"なってない"といわざるを得ないではない。

計算方法を変える

計算方針を考える
落ち着こう。確かに無理数は避けて通れない。しかし、我々は無理数どころか、"もっとスゴい"数を扱ったことがあるはずだ。そう、二乗すると -1 になっちゃう愛に溢れた"アレ"を含む数、複素数である。
複素数をどう扱ったか思い出そう。次のように表現したはずだ。
$a+bi$
虚数単位 $i$ はもはや無理数ですらない。それでも我々は扱ってきた。ならばたかが $\sqrt$ 程度が扱えないわけがない。
というわけで、複素数の i を $\sqrt$ に置き換えた形で今回の式を取り扱うことにしよう。
フィボナッチ数列の一般項を計算する(※ただし有理数に限る)

Haskellでは標準で Rational という有理数を扱う型があるが、Pythonでは標準 fractions を使うと分数(有理数)での計算ができる。

FibNum こと Rational の二要素からなるタプルは、左に $\sqrt$ が付かない項を、右に $\sqrt$ が付く項を格納することしよう。つまり (1, 1) と書けば $1+\sqrt$ のこと。(0, 1) と書けば $\sqrt$ のこと。(1 % 2, 1 % 3) と書けば $\frac+\frac\sqrt$ のことを表す。(中略)
除算は 0 で割れないとか面倒なこともあるので、乗算の形にしておきたい。
まず、(整数の公式でフィボナッチ数列を求める 1, 1) `fibDiv` (2, 0) は要するに $\frac<1+\sqrt>$ のことだが、こんなものは $\frac+\frac\sqrt$、つまり (1 % 2, 1 % 2) としてしまえば良い。
後ろ側の 整数の公式でフィボナッチ数列を求める $\sqrt$ で割る処理は、逆数であるところの $\frac<\sqrt>$ 、つまり $\frac<\sqrt>$ を掛ければ良い。$\frac<\sqrt>$ ってことは $0+\frac\sqrt$ だから、ここでの表現では (0, 整数の公式でフィボナッチ数列を求める 1 % 5) ってことだ。

関連記事

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする

目次
閉じる