« 白髭咲き | トップページ | イヌノフグリ »

2014年11月26日 (水)

連分数の求め方

http://yamada-kuebiko.cocolog-nifty.com/blog/2014/11/post-6140.html
2014年11月25日 (火)「連分数」
この記事中で下のようなことを書きました。

・・・
2.7182818284590452353602874713527 を
「整数部と小数部に分けます。」
「小数部は1より大きい数の逆数で表せますね。」
というようにして、果てしなく続けることができます。
正直なところ、実に面倒くさい。
・・・

「整数部と小数部に分けて、小数部の逆数をとって」という『単純』な作業を『果てしなく』続けることになるのでした。
そういうのって、実はコンピューター向けなんですよね。コンピューターは疲れを知らない。言われた通りの単純作業を、こちらがいいよ、というまで続けてくれます。
実例をお目にかけましょう。
十進BASICで書いてみました。
--------------------
OPTION BASE 0
LET MAX = 15
DIM a(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

END
--------------------
細かいところは抜きにして。
次々に得られる整数部を a( )という配列に順番に収納することにします。
配列というのは複数の記憶内容を番号で操作できるので便利な仕組みです。
変数 n に求めたい無理数を入れます。
手入力は面倒なので、ウィンドウズの電卓で得られる数値をプログラムに書き込み、使わないものは「!」でコメントにしてしまいます。
上の例では e を生かして、他はコメントアウト。

その下、最初のFOR ~ NEXTの部分が『単純作業の繰り返し』です。
INT() という関数は、整数部を取り出してくれます。
「n - INT(n)」で小数部を取り出して
「n = 1 / (n - a(i))」その小数部の逆数をとる。
この操作を、MAX 回繰り返す。というループです。
このプログラムでは「MAX = 15」にしてあります。
コンピューター自体は疲れを知らないとしても逆数をとるという計算のたびに誤差が生じて蓄積していきます。
あまりむやみに回数だけ増やしても意味がありません。

eで実行してみるとこう↓なりました。
e: 2   1   2   1   1   4   1   1   6   1   1   8   1   1   10   1 
いいようですね。
分子がすべて「1」であるような連分数を正則連分数といいますが、正則連分数の求め方はこれで一応出来上がりました。

π  : 3   7   15   1   292   1   1   1   2   1   3   1   12   2   2   1 
φ  : 1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1 
√2: 1   2   2   2   2   2   2   2   2   2   2   2   2   2   2   2 
√3: 1   1   2   1   2   1   2   1   2   1   2   1   2   1   2   1 
いくつかの例です。
πはちょっと不規則なようですが、平方根がらみは規則正しいですね。

★実は十進BASICには次のような関数があります。

IP(x)      SGN(x)*INT(ABS(x))  xの整数部分 (Integer Part)
                  例 IP(5.4)=5, IP(5)=5, IP(-4.4)=-4
FP(x)     x-IP(x)  xの小数部分 (Fraction Part)

当然この関数は今回使えますが、他の言語には備えられていない可能性があります。
Cなら「modf()」という関数がありまして、浮動小数点の値を与えると、関数の返り値として小数部が返され、整数部は配列の中にしまってきてくれます。これも今回の目的にはいい関数ですが、このBASICにはない。
ところが整数部を取り出すだけの関数は、名前がINTかどうかは別として、大抵の言語に備わっています。
ですから、効率とかいうことをあまり考えなくてよいのなら、だれが読んでもどの言語でも苦労せずに移植できるように明瞭にアルゴリズムを書くのがよいのです。
私は多言語を自学自習したたちですので、アルゴリズムの移植には随分大変な思いをしました。
言語特有の能力を駆使するのは気持ちよくってかっこいいんですが、ちょっとね。移植性も考えましょう。

★次はこの連分数を近似分数にするにはどうしたらいいか、考えます。ちょっと厄介そうですね。

« 白髭咲き | トップページ | イヌノフグリ »

理科おじさん」カテゴリの記事

コメント

コメントを書く

(ウェブ上には掲載しません)

« 白髭咲き | トップページ | イヌノフグリ »

2021年5月
            1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31          
サイト内検索
ココログ最強検索 by 暴想
無料ブログはココログ