連分数から近似分数を作る
★
http://yamada-kuebiko.cocolog-nifty.com/blog/2014/11/post-1095.html
2014年11月26日 (水)「連分数の求め方」
正則連分数の求め方はこれで一応出来上がりました。
次はこの連分数を近似分数にするにはどうしたらいいか、考えます。ちょっと厄介そうですね。
前回はここまで↑きています。
★おさらい
上が連分数表記。
下が省スペースの書き方。{私は面倒くさいので、ただ数を「スペース」で区切っただけで並べていることが多いです。ご了解ください。}
・連分数表記で、a1以降を切り捨てたものを「第0次近似」といいます。
「a0/1」という分数だと理解してください。
・a2以降を切り捨てると「a0+1/a1」となります。
「(a0a1+1)/a1」という分数ですね。
これが第1次近似。
・a3以降を切り捨てると第2次近似です。
以下同文。
★面倒くさいのですが、やってみましょう。
第2次近似でも何となく規則性が見えているのですが、第3次近似までいくと規則性が確実になります。
図の一番下です。
pi=aipi-1+pi-2
qi=aiqi-1+qi-2
これですね。
i番目の分母分子を求めるのに、2つ前までの値を利用しています。
ですから、i=1,2については、それぞれの値を求めておけば
i=3以降は繰り返しでやれそうです。
この方針でプログラムを書いてみました。
--------------------
OPTION BASE 0
LET MAX = 10
DIM a(MAX), p(MAX), q(MAX)
!LET n = 3.1415926535897932384626433832795 !π
LET n = 2.7182818284590452353602874713527 !e
!LET n = 1.6180339887498948482045868343656 !φ
!LET n = 1.4142135623730950488016887242097 !√2
!LET n = 1.7320508075688772935274463415059 !√3
FOR i = 0 TO MAX
LET a(i) = INT(n)
LET n = 1 / (n - a(i))
NEXT i
FOR i = 0 TO MAX
PRINT a(i);" ";
NEXT i
PRINT
LET p(0) = a(0)
LET q(0) = 1
PRINT p(0);"/";q(0);"=";p(0)/q(0)
LET p(1) = a(0) * a(1) + 1
LET q(1) = a(1)
PRINT p(1);"/";q(1);"=";p(1)/q(1)
FOR i = 2 TO MAX
LET p(i) = a(i) * p(i-1) + p(i-2)
LET q(i) = a(i) * q(i-1) + q(i-2)
PRINT p(i);"/";q(i);"=";p(i)/q(i)
NEXT i
END
--------------------
プログラムの前半はeの値から、連分数を生成する部分。{前回のものです}
そこへ今回の考え方を書きます。
p(0)、q(0) と
p(1)、q(1) は
それぞれ書きます。
その後に、「前2つの値を使う」という考えにより、FOR~NEXTループで近似分数を作っていきます。
ではeについての結果をご覧ください。↓
--------------------
2 1 2 1 1 4 1 1 6 1 1
2 / 1 = 2
3 / 1 = 3
8 / 3 = 2.66666666666667
11 / 4 = 2.75
19 / 7 = 2.71428571428571
87 / 32 = 2.71875
106 / 39 = 2.71794871794872
193 / 71 = 2.71830985915493
1264 / 465 = 2.71827956989247
1457 / 536 = 2.71828358208955
2721 / 1001 = 2.71828171828172
--------------------
正しい値より「小さい・大きい・小さい・大きい・・・」を繰り返しながら近似が進んでいく様子が見えます。
第10次近似で2.718281までの一致を見ました。
まあ、なかなかのものですね。
有限の長さの小数としてしか扱えないので、どうしても誤差が蓄積します。
あまり近似を進めすぎるとかえって不正確になる恐れもありますから、ご注意を。
★ところで
「πとeの話」YEO・エイドリアン[著]、久保儀明+蓮見亮[訳]、青土社
この本のp.89にこんな記述があります。
eに小数点以下4桁まで正確な数値を与える、ある程度の調和美を備えている簡潔な分数は878/323である。
あれ?
連分数から作った近似分数の中に「878/323」はないですね。
分母71から分母465へ飛んでしまった。323は飛ばされちゃったぞ。
分母が1桁から2桁へ、2桁から3ケタへ、というジャンプがありますが、これは「1 1 4 1 1 6…」という並びの、4、6という大きな数の出現と関連があるようですね。
さて、そうなのか。連分数に依らずに、「878/323」を生み出すようなアルゴリズムを考えなくっちゃいけませんね。
あらまあ。いいけどさ。
★ちなみに、プログラム中でコメントアウトしてある他の数、πやφ、√2、√3を試した結果をファイルとしてお目にかけます。πはそのうち蒸し返すつもりでいます。ご覧ください。
「KinjiBunsu.txt」をダウンロード
「理科おじさん」カテゴリの記事
- 化学の日(2022.10.26)
- 秒速→時速(2022.09.01)
- 風速75メートル(2022.08.31)
- 「ウクライナで生まれた科学者たち」(2022.05.31)
- 反射光(2022.05.09)
このプログラムでproject euler problem65を
解くことはできるでしょうか。
投稿: M&A | 2022年12月31日 (土) 06時53分
コメントありがとうございます。年末年始いろいろあって、遅くなりました。
プログラムの論理自体はいいと思いますが、PCの能力に問題があるのではないでしょうか。多倍長計算ができませんので、ちょっといくと、誤差の積み重ね、ゴミだらけになってしまうはずです。せめて100桁あれば、先も見えるでしょうけれど。
こんなご返事でスミマセン。今後ともよろしく。
投稿: かかし | 2023年1月 9日 (月) 14時37分
回答ありがとうございました。
投稿: | 2023年1月11日 (水) 08時34分