√Nの計算 |
平方根 √A のニュートン法による漸化式
Xn+1 := (Xn + A /
Xn) /
2
繰り返す回数は、100万桁≒2の20乗 20回。
1億桁なら、≒2の26.5乗→27回。
A /
Xnは、多倍長÷多倍長の形なので計算が複雑になる。
――――――――――――――――――――――――――――――――――――――――――――――――――
1
/ √A のニュートン法による漸化式
Xn+1: = Xn * (3 - A * Xn2) / 2 <乗算回数 5回 係数含>
これだと回数は多いが 多倍長÷多倍長はなくなる。
※2の割算があるが、0.5倍と考えれば、すべて乗算になる。
√A= A * (1 / √A) であるから、
1 /
√Aがわかれば、√Aが 乗算でもとめられる。
――――――――――――――――――――――――――――――――――――――――――――――――――
! √Nの計算 百桁区切り 十進BASIC
! 1/√Nの漸化式
! Xn+1: = Xn+1: = Xn * (3 - A * Xn2) / 2
!
OPTION ARITHMETIC
DECIMAL_HIGH
!――――――――入力条件―――――――――――――――
DO
DO
DO
input PROMPT
"N=":N
if int(N)<>N then print "正の整数しか計算できません"
loop until
int(N)=N
if int(sqr(N))=sqr(N) then print "平方数かも知れません"
loop while
int(sqr(N))=sqr(N)
if N>10^6 then print "1000000超えると計算できません"
loop while
N>1000000
DO
DO
input PROMPT "桁数は? (1000単位で)":KTA
loop while
KTA<2000
loop until
KTA/1000=int(KTA/1000)
!―――――――――――――――――――――――――――
print "計算開始
";date$;" ";time$
print "桁数=";KTA;"桁"
! 100桁区切り
LET
BLOCK=int(KTA*1.1/100) ! マージン10%とする
print
"BLOCK=";BLOCK
!――――――――宣言文――――――――――――――――
option base 0
dim
XN0(BLOCK),XN1(BLOCK),A(BLOCK),XN02(BLOCK)
dim
AXN02(BLOCK),AXN02m3(BLOCK),AXN02m3X(BLOCK)
dim
OPT5(BLOCK)
!―――――――初期化―――――――――――――――――
LET KS=0
gosub 20000 !
まず初期化
!―――――――計算回数の計算―――――――――――――
10 !
DO
LET
KS=KS+1
loop while KTA >
2^KS
!―――――――エンジン部分―――――――――――――
print "KS=";KS+1
for K=0
to KS+1
print "計算";K;"回目";TIME$
gosub 100 ! 計算ルーチン本体部分
next
K
!―――――――――――――――――――――――――――
!――――最終処理
√N=N×(1/√N)―――――――――――
FOR I=0 to BLOCK
LET XN0(I)=N*XN0(I)
next
I
20 ! 桁処理 --桁上げ処理
Do
LET OBF=0
for I=BLOCK TO 1 step -1
LET
XN0(I-1)=XN0(I-1)+int(XN0(I)/10^100)
LET
XN0(I)=XN0(I)-10^100*int(XN0(I)/10^100)
if XN0(I)>10^100 then LET
OBF=1
NEXT I
loop while
OBF=1
!―――終了終了終了終了終了終了終了終了終了終了終了――――
!印刷印刷印刷印刷印刷印刷印刷印刷印刷印刷印刷印刷印刷印刷印刷印刷印刷印刷印刷印刷印刷印刷印刷
print
"終了!"
print "計算終了 ";date$;" ";time$
print str$(XN0(0));"."
for I=1
TO BLOCK
LET p$=repeat$("0",100-len(str$(XN0(I))))&str$(XN0(I))
print
MID$(p$,1,10);" ";MID$(p$,11,10);" ";MID$(p$,21,10);" ";MID$(p$,31,10);"
";MID$(p$,41,10);" ";
print MID$(p$,51,10);" ";MID$(p$,61,10);"
";MID$(p$,71,10);" ";MID$(p$,81,10);" ";MID$(p$,91,10);" "
if int(I/10)=I/10
then print I*100;"桁目"
next
I
!印刷印刷印刷印刷印刷印刷印刷印刷印刷印刷印刷印刷印刷印刷印刷印刷印刷印刷印刷印刷印刷印刷印刷
stop
100 !
! Xn+1: = Xn * (3 - A * Xn2) / 2
! @Xn^2の計算
for I=0 TO
BLOCK
for J=0 TO BLOCK-I
LET XN02(I+J)=XN0(I)*XN0(J)+XN02(I+J)
next
J
next I
! AA*Xn^2の計算
for I=0 TO BLOCK
for J=0 TO BLOCK-I
LET
AXN02(I+J)=A(I)*XN02(J)+AXN02(I+J)
next J
next I
! B3−A *
Xn^2の計算
LET AXN02m3(0)=3
for I=0 TO BLOCK
LET
AXN02m3(I)=AXN02m3(I)-AXN02(I)
next I
! CXn*(3 -A* Xn^2)の計算
for I=0
TO BLOCK
for J=0 TO BLOCK-I
LET
AXN02m3X(I+J)=XN0(I)*AXN02m3(J)+AXN02m3X(I+J)
next J
next I
!
D0.5*Xn*(3 -A* Xn^2)の計算
for I=0 TO BLOCK
for J=0 TO BLOCK-I
LET
XN1(I+J)=AXN02m3X(I)*OPT5(J)+XN1(I+J)
next J
next I
1000 ! 桁処理1
--負記号の削除
DO
LET MNSF=0
if XN1(1)<0 then
LET
XN1(0)=XN1(0)+int(XN1(1)/10^100)-1
LET
XN1(1)=XN1(1)-10^100*int(XN1(1)/10^100)+10^100
end if
for I=BLOCK TO 1
step -1
if XN1(I)<0 then
LET MNSF=1
LET
XN1(I-1)=XN1(I-1)+int(XN1(I)/10^100)-1
LET
XN1(I)=XN1(I)-10^100*int(XN1(I)/10^100)+10^100
end if
NEXT I
LOOP while
MNSF=1
2000 ! 桁処理2 --桁上げ処理
DO
LET OBF=0
for I=BLOCK TO 1
step -1
LET XN1(I-1)=XN1(I-1)+int(XN1(I)/10^100)
LET
XN1(I)=XN1(I)-10^100*int(XN1(I)/10^100)
if XN1(I)>10^100 then
LET
OBF=1
end if
NEXT I
loop while OBF=1
3000 ! XN1 => XN0
へ入替
for I=0 to BLOCK
LET XN0(I)=XN1(I)
NEXT I
!2回目以降の初期化
2回目以降の初期化2回目以降の初期化2回目以降の初期化2回目以降の初期化2回目以降の初期化
for I=0 To BLOCK
LET
A(I)=0
! XN0(I)=0 2回目の初期化では『0』にしない。
LET XN1(I)=0
LET XN02(I)=0
LET
AXN02(I)=0
LET AXN02m3(I)=0
LET AXN02m3X(I)=0
! LET OPT5(I)=0
next
I
LET A(0)=N
LET OPT5(0)=0 ! 0.5
LET OPT5(1)=5*10^99 !
0.5
return
20000 !初期設定 初期設定 初期設定 初期設定 初期設定 初期設定 初期設定 初期設定 初期設定
初期設定
for I=0 To BLOCK
LET A(I)=0
LET XN0(I)=0
LET XN1(I)=0
LET
XN02(I)=0
LET AXN02(I)=0
LET AXN02m3(I)=0
LET AXN02m3X(I)=0
LET
OPT5(I)=0
next I
LET XN0(0)=int(1/sqr(N)) ! 1/√N
LET
XN0(1)=int((1/sqr(N)-int(1/sqr(N)))*1000)*10^(100-3)
LET A(0)=N
LET
OPT5(0)=0 ! 0.5
LET OPT5(1)=5*10^99 !
0.5
return
END