新しく発言する  EXIT  インデックスへ

1000桁モードでの数値演算の桁あふれ


  1000桁モードでの数値演算の桁あふれ 山中和義 2008/07/28 20:24:41 
  KK62526です。 KK62526 2008/07/29 22:00:17 
  │└この件が解決した後、報告しようと思ってい... 山中和義 2008/07/30 10:10:51 
  │ └的確なご指摘、どうもありがとうございます... KK62526 2008/07/31 08:30:34 
  1000桁モードでの数値の指数部の扱いが構文... 山中和義 2008/07/30 10:02:43 
  │└現象の解析、どうもありがとうございました... KK62526 2008/07/31 08:31:32 
  再帰的な書き方に慣れるために KK62526 2008/08/01 00:28:51 

  1000桁モードでの数値演算の桁あふれ 山中和義 2008/07/28 20:24:41   ツリーへ
1000桁モードでの数値演算の桁あふれ  返事を書く  ノートメニュー
山中和義 <drdlxujciw> 2008/07/28 20:24:41
下記の2つのプログラム(πをn桁もとめる)で動作が異なります。

プログラム1では、n=194以上で桁あふれが発生します。


●プログラム1

OPTION ARITHMETIC decimal_high
!OPTION ARITHMETIC RATIONAL

INPUT PROMPT "計算したい桁数 ": n
PRINT "円周率を";n;"桁求める。"

LET q1 = 1
LET r1 = 180
LET t1 = 60
LET i1 = 2

FOR i = 1 TO n
LET u1 = 3 * (3 * i1 + 1) * (3 * i1 + 2)
LET y1 = INT((q1 * (27 * i1 - 12) + 5 * r1) / (5 * t1) )

PRINT USING "#": y1;

LET q2 = 10 * q1 * i1 * (2 * i1 - 1)
LET r2 = 10 * u1 * (q1 * (5 * i1 - 2) + r1 - y1 * t1) !<-----
LET t2 = t1 * u1
LET i2 = i1 + 1

LET q1 = q2
LET r1 = r2
LET t1 = t2
LET i1 = i2
NEXT i

END



●プログラム2

OPTION ARITHMETIC decimal_high
!OPTION ARITHMETIC RATIONAL

PUBLIC NUMERIC n

INPUT PROMPT "計算したい桁数 ": n
PRINT "円周率を";n;"桁求める。"

CALL g(1,180,60,2)

PRINT
PRINT PI !検算

END


EXTERNAL SUB g(q,r,t,i)
OPTION ARITHMETIC decimal_high
!OPTION ARITHMETIC RATIONAL
LET u=3*(3*i+1)*(3*i+2)
LET y=INT((q*(27*i-12)+5*r)/(5*t))
PRINT USING "#": y;
IF i>n THEN EXIT SUB
CALL g(10*q*i*(2*i-1), 10*u*(q*(5*i-2)+r-y*t), t*u, i+1)
END SUB
  KK62526です。 KK62526 2008/07/29 22:00:17   ツリーへ
Re: 1000桁モードでの数値演算の桁あふれ  返事を書く  ノートメニュー
KK62526 <vrgekmpzvy> 2008/07/29 22:00:17
KK62526です。

山中さん。円周率計算に関する件、ご教示
どうもありがとうございました。
当方でもプログラム2で、1000桁の計算でも、
桁あふれを起こさないことを確認いたしました。

こちらのプログラムの方が、もともとの
Gibbonsによるこつこつアルゴリズムを
十進BASICに移植したことが分かりやすく、
はるかに見通しがすっきりしております。

私のような初心者にとって、ベテランの方から
直接レスポンスを頂けますと、とても励みに
なります。どうもありがとうございました。
  │└この件が解決した後、報告しようと思ってい... 山中和義 2008/07/30 10:10:51   ツリーへ
Re: KK62526です。  返事を書く  ノートメニュー
山中和義 <drdlxujciw> 2008/07/30 10:10:51
この件が解決した後、報告しようと思っていました。

オリジナルのプログラムは
・無限の多桁整数
・無限の再帰呼出し
を前提にしているようですので、

スタックのオーバーフローが発生しない、繰り返しのプログラム(KK62526さんのプログラム)を、
有理数モードで実行するのがいいかと思います。
  │ └的確なご指摘、どうもありがとうございます... KK62526 2008/07/31 08:30:34   ツリーへ
Re: この件が解決した後、報告しようと思ってい...  返事を書く  ノートメニュー
KK62526 <vrgekmpzvy> 2008/07/31 08:30:34
的確なご指摘、どうもありがとうございます。

ご指摘の通り、Haskell言語は、無限の取り扱いに関して、
・無限の多桁整数
・無限の再帰呼出し
という特徴を有しています。有限の結果を得たい
場合は、
・まず、無限の関係式(漸化式など)を書き下す。
・ついで、ほしい有限の部分を切り出す。
というアプローチを取ります。

今後、Haskell言語のプログラムを十進BASICに移植
する際にも、気をつけたいと思います。
ありがとうございました。
  1000桁モードでの数値の指数部の扱いが構文... 山中和義 2008/07/30 10:02:43   ツリーへ
Re: 1000桁モードでの数値演算の桁あふれ  返事を書く  ノートメニュー
山中和義 <drdlxujciw> 2008/07/30 10:02:43
1000桁モードでの数値の指数部の扱いが構文により異なるようです。

この現象で桁あふれが発生しているようです。



OPTION ARITHMETIC decimal_high

LET a=1e1000


!LET b=1e1009 !定数 仮数と指数


!LET b=a*1000000000 !LET文の式


DEF f(a)=a*1000000000 !関数
!LET b=f(a)


FUNCTION ff(a)
LET ff=a
END FUNCTION
!PRINT ff(a*1000000000) !関数の引数


!SELECT CASE a*1000000000 !CASE文の式
!CASE 1
!CASE ELSE
!END SELECT


SUB g(a)
PRINT a
END SUB
CALL g(a*1000000000) !サブルーチン文の引数


IF a*1000000000>0 THEN LET c=1 !条件式


END
  │└現象の解析、どうもありがとうございました... KK62526 2008/07/31 08:31:32   ツリーへ
Re: 1000桁モードでの数値の指数部の扱いが構文...  返事を書く  ノートメニュー
KK62526 <vrgekmpzvy> 2008/07/31 08:31:32
現象の解析、どうもありがとうございました。

理由が分かり、大変参考になりました。
今後、多数桁の計算を行うとき、気をつけたいと
思います。
  再帰的な書き方に慣れるために KK62526 2008/08/01 00:28:51   ツリーへ
Re: 1000桁モードでの数値演算の桁あふれ  返事を書く  ノートメニュー
KK62526 <vrgekmpzvy> 2008/08/01 00:28:51
再帰的な書き方に慣れるために

十進BASICでも、再帰的な記述に慣れることが必要と
感じました。円周率の計算に関して、何かよい例が
ないか考えましたところ、Binary Splittingが最適
と思い至り、新たにコンテンツを増やしてみました。

Binary Splittingは、高速に級数の和をとるときに
必須のテクニックで、円周率の計算でも、しばしば
用いられます。

URLアドレスを示します。
http://www14.ocn.ne.jp/~kk62526/pi/BinSplit.html
PiChudnovsky.BAS......Chudnovskyの無限級数の計算(非再帰版)
PiChudnovskyR.BAS.....Chudnovskyの無限級数の計算(再帰版)
PiTakano_MadhavaGregoryLeibniz.BAS....高野の公式の計算(非再帰版)
PiTakano_MadhavaGregoryLeibnizR.BAS...高野の公式の計算(再帰版)
PiTakano_Euler.BAS....高野の公式の計算(非再帰版)
PiTakano_EulerR.BAS...高野の公式の計算(再帰版)

よろしくお願い申し上げます。

 インデックスへ  EXIT
新規発言を反映させるにはブラウザの更新ボタンを押してください。