2018年3月17日土曜日

円周率の近似値を求める手法

藤堂様からお知らせ戴きました、つぎのblog様に、とても興味深い情報がありました。

cf. 円周率の近似値となる分数を算出するワンライナー - すぎゃーんメモ 様
http://memo.sugyan.com/entry/20090708/1247044465

Perl言語によるone liner (1行スクリプト)で、円周率に近い分数を検索する、というものです。
ただ、当方はPerlとか正規表現とか、ちんぷんかんぷんなのですヨ。
そこで、上記blog様にある1行スクリプトを凝視するコト数時間、やっている事がおぼろげに判ってきました。
  1. 分母を1から始めて、10000などの上限に達するまで、ループで調べる
  2. 円周率に近い分数であるから、その分子は分母の円周率倍の整数であれば良かろう
  3. こうして分数をでっち上げ、正規表現による精度の確認
という感じらしい。そうか、その手があったのか !

内容としては簡単なものなのですが、それをPerlスクリプトでサラリと書いてしまう辺り、大変勉強になります。
ここでは、同等の機能をBASIC ! (AndroidのRFO BASIC)で行ってみました。電卓で実行するにしても、BASICならば書き換えやすいと思います。

件のone linerでは、円周率近似値を出力する目的を簡単に済ませるものなので、約分まではやりません。必要ならば、別のone linerにパイプするなど、ユーザーが行えば宜しい、という具合。
そこで、BASIC ! プログラムでは、互除法を用いて約分する機能も盛り付けてみました。正確には、約分出来そうな場合には、出力しない様になっております。

プログラム中の変数 d は、円周率と判断する誤差の範囲を指定するもので、これを所望の精度に合わせて変更する事で、分数の絞り込みが出来ます。
電卓で実行するとなると、上限は10000くらいが良さそうです。後は、ユーザーの責任にて実行されたし !


リスト「pseudo-pi.bas」 (Android RFO BASIC 用)


REM Start of BASIC! Program

! title : pseudo-pi.bas
! begin : 2018-03-15 18:13
! note  : 分母を1から順番に検索し、近似値分数が分数を出力する

! precision
d = 0.000001

! pi
pi = atan(1)*4

!  検索ループ
for j = 1 to 10000
  ! 近似値分数を生成
  i = int(j * pi + 0.5)
  ! 近似値分数が精度の範囲内ならば、
  if abs(i/j - pi) <= d 
    ! 互除法で通分可能か調べる
    s = i
    t = j
    while mod(s,t) <> 0
      r = mod(s, t)
      s = t
      t = r
    repeat
    ! 通分出来ない場合、出力
    if r = 1
      print i, j, i/j
!    else 
!      print "..."
    endif

  endif

next j

end