投稿者:山中和義
投稿日:2011年 9月18日(日)16時53分11秒
|
|
|
十進モードでは、不正な値(答え)になる。
1000桁モードでは、INT関数が桁あふれする。
!多項式に対する拡張ユークリッド互除法
!多項式f(x)=A[m]x^m+ … +A[1]x+A[0]、g(x)=B[n]x^n+ … +B[1]x+B[0]、m≧nとして、
!f(x)S(x)+g(x)T(x)=gcd(f(x),g(x))=C(x)となるS(x),T(x),C(x)を求める。
PUBLIC NUMERIC MAX_DEGREE !次数 ※m^2以上
LET MAX_DEGREE=10
!------------------------------
DATA 3 !次数
DATA 1,0,-3,1 !g(x)=x^3-3x+1
DATA 3
DATA 1,1,0,6 !f(x)=x^3+x^2+6
READ M !次数
DIM A(0 TO M) !係数
FOR i=M TO 0 STEP -1 !f(x)=A[m]x^m+ … +A[1]x+A[0]
READ A(i)
NEXT i
READ N !次数
DIM B(0 TO N) !係数
FOR i=N TO 0 STEP -1 !g(x)=B[n]x^n+ … +B[1]x+B[0]
READ B(i)
NEXT i
DIM P(0 TO MAX_DEGREE),Q(0 TO MAX_DEGREE),C(0 TO MAX_DEGREE)
MAT P=ZER
MAT Q=ZER
MAT C=ZER
CALL ExGCD(M,A,N,B, pp,P,qq,Q,cc,C) !拡張ユークリッド互除法
MAT PRINT P; !結果を表示する
MAT PRINT Q;
MAT PRINT C;
END
!拡張ユークリッド互除法
! f(x)=A[m]x^m+ … +A[1]x+A[0]、g(x)=B[n]x^n+ … +B[1]x+B[0]、m≧nとして、
! f(x)S(x)+g(x)T(x)=gcd(f(x),g(x))=C(x)となるS(x),T(x),C(x)を求める。
EXTERNAL SUB ExGCD(aa,A(),bb,B(), ss,S(),tt,T(),cc,C()) !拡張ユークリッド互除法
IF bb=0 AND B(0)=0 THEN !IF b=0 THEN
LET S(0)=1 !s=1 ※f(x)*1+0*0=f(x)とする
LET ss=0
LET T(0)=0 !t=0
LET tt=0
MAT C=A !c=a
LET cc=aa
ELSE
DIM Q(0 TO MAX_DEGREE),R(0 TO MAX_DEGREE)
IF aa=0 AND bb=0 THEN !定数項のみ
LET Q(0)=INT(A(0)/B(0))
LET qq=0
LET R(0)=MOD(A(0),B(0))
LET rr=0
ELSE
CALL poly_div(aa,A,bb,B, qq,Q,rr,R) !q=INT(a/b), r=MOD(a,b)
END IF
CALL ExGCD(bb,B,rr,R, tt,T,ss,S,cc,C) !k=n-1,…,3,2 まで続ける
DIM W(0 TO MAX_DEGREE)
CALL poly_mul(ss,S,qq,Q, ww,W) ! t=u-v*q
MAT T=T-W
LET tt=ww
END IF
END SUB
!補助ルーチン
!演算関連
EXTERNAL SUB poly_mul(aa,A(),bb,B(), ss,S()) !乗算 S=A*B ※S≠A、S≠B
FOR i=aa TO 0 STEP -1
FOR j=bb TO 0 STEP -1
LET S(i+j)=S(i+j)+A(i)*B(j) !すべての係数をかける
NEXT j
NEXT i
LET ss=aa+bb !次数
END SUB
EXTERNAL SUB poly_div(aa,A(),bb,B(), qq,Q(),rr,R()) !除算 ※被除数=商*除数+余り
IF bb=0 AND B(0)=0 THEN !0なら
PRINT "0で割ることはできません。"
STOP
ELSE
MAT Q=ZER !商
MAT R=ZER !余り
MAT R=A
FOR t=aa TO bb STEP -1 !被除数の次数が除数のより大きいなら
IF R(t)<>0 THEN !係数が0以外なら
LET k=R(t)/B(bb) !商の係数、その次数
LET w=t-bb
LET Q(w)=k !商
FOR i=bb TO 0 STEP -1 !余り ※R=A-k*B
LET R(w+i)=R(w+i)-k*B(i)
NEXT i
END IF
NEXT t
LET qq=MAX(aa-bb,0) !次数
IF aa>=bb THEN LET rr=MAX(bb-1,0) ELSE LET rr=aa
END IF
END SUB
|
|
|
投稿者:白石和夫
投稿日:2011年 9月18日(日)17時56分27秒
|
|
|
> No.1663[元記事へ]
2005行と2065行を追加しました。
有理数モードで正しい答えになるようであれば,2000行と2050行の計算誤差が原因ではないでしょうか。
1000 !多項式に対する拡張ユークリッド互除法
1010
1020 !多項式f(x)=A[m]x^m+ … +A[1]x+A[0]、g(x)=B[n]x^n+ … +B[1]x+B[0]、m≧nとして、
1030 !f(x)S(x)+g(x)T(x)=gcd(f(x),g(x))=C(x)となるS(x),T(x),C(x)を求める。
1040
1050 PUBLIC NUMERIC MAX_DEGREE !次数 ※m^2以上
1060 LET MAX_DEGREE=10
1070 !------------------------------
1080
1090
1100 DATA 3 !次数
1110 DATA 1,0,-3,1 !g(x)=x^3-3x+1
1120 DATA 3
1130 DATA 1,1,0,6 !f(x)=x^3+x^2+6
1140
1150
1160 READ M !次数
1170 DIM A(0 TO M) !係数
1180 FOR i=M TO 0 STEP -1 !f(x)=A[m]x^m+ … +A[1]x+A[0]
1190 READ A(i)
1200 NEXT i
1210
1220 READ N !次数
1230 DIM B(0 TO N) !係数
1240 FOR i=N TO 0 STEP -1 !g(x)=B[n]x^n+ … +B[1]x+B[0]
1250 READ B(i)
1260 NEXT i
1270
1280
1290 DIM P(0 TO MAX_DEGREE),Q(0 TO MAX_DEGREE),C(0 TO MAX_DEGREE)
1300 MAT P=ZER
1310 MAT Q=ZER
1320 MAT C=ZER
1330 CALL ExGCD(M,A,N,B, pp,P,qq,Q,cc,C) !拡張ユークリッド互除法
1340
1350
1360 MAT PRINT P; !結果を表示する
1370 MAT PRINT Q;
1380 MAT PRINT C;
1390
1400 END
1410
1420
1430 !拡張ユークリッド互除法
1440 ! f(x)=A[m]x^m+ … +A[1]x+A[0]、g(x)=B[n]x^n+ … +B[1]x+B[0]、m≧nとして、
1450 ! f(x)S(x)+g(x)T(x)=gcd(f(x),g(x))=C(x)となるS(x),T(x),C(x)を求める。
1460
1470 EXTERNAL SUB ExGCD(aa,A(),bb,B(), ss,S(),tt,T(),cc,C()) !拡張ユークリッド互除法
1480 IF bb=0 AND B(0)=0 THEN !IF b=0 THEN
1490 LET S(0)=1 !s=1 ※f(x)*1+0*0=f(x)とする
1500 LET ss=0
1510 LET T(0)=0 !t=0
1520 LET tt=0
1530 MAT C=A !c=a
1540 LET cc=aa
1550 ELSE
1560 DIM Q(0 TO MAX_DEGREE),R(0 TO MAX_DEGREE)
1570 IF aa=0 AND bb=0 THEN !定数項のみ
1580 LET Q(0)=INT(A(0)/B(0))
1590 LET qq=0
1600 LET R(0)=MOD(A(0),B(0))
1610 LET rr=0
1620 ELSE
1630 CALL poly_div(aa,A,bb,B, qq,Q,rr,R) !q=INT(a/b), r=MOD(a,b)
1640 END IF
1650
1660 CALL ExGCD(bb,B,rr,R, tt,T,ss,S,cc,C) !k=n-1,…,3,2 まで続ける
1670
1680 DIM W(0 TO MAX_DEGREE)
1690 CALL poly_mul(ss,S,qq,Q, ww,W) ! t=u-v*q
1700 MAT T=T-W
1710 LET tt=ww
1720 END IF
1730 END SUB
1740
1750
1760 !補助ルーチン
1770
1780 !演算関連
1790
1800 EXTERNAL SUB poly_mul(aa,A(),bb,B(), ss,S()) !乗算 S=A*B ※S≠A、S≠B
1810 FOR i=aa TO 0 STEP -1
1820 FOR j=bb TO 0 STEP -1
1830 LET S(i+j)=S(i+j)+A(i)*B(j) !すべての係数をかける
1840 NEXT j
1850 NEXT i
1860 LET ss=aa+bb !次数
1870 END SUB
1880
1890
1900 EXTERNAL SUB poly_div(aa,A(),bb,B(), qq,Q(),rr,R()) !除算 ※被除数=商*除数+余り
1910 IF bb=0 AND B(0)=0 THEN !0なら
1920 PRINT "0で割ることはできません。"
1930 STOP
1940 ELSE
1950 MAT Q=ZER !商
1960 MAT R=ZER !余り
1970 MAT R=A
1980 FOR t=aa TO bb STEP -1 !被除数の次数が除数のより大きいなら
1990 IF R(t)<>0 THEN !係数が0以外なら
2000 LET k=R(t)/B(bb) !商の係数、その次数
2005 PRINT k
2010 LET w=t-bb
2020 LET Q(w)=k !商
2030
2040 FOR i=bb TO 0 STEP -1 !余り ※R=A-k*B
2050 LET R(w+i)=R(w+i)-k*B(i)
2060 NEXT i
2065 MAT PRINT R
2070 END IF
2080 NEXT t
2090 LET qq=MAX(aa-bb,0) !次数
2100 IF aa>=bb THEN LET rr=MAX(bb-1,0) ELSE LET rr=aa
2110 END IF
2120 END SUB
|
|
|
投稿者:山中和義
投稿日:2011年 9月18日(日)19時28分52秒
|
|
|
> No.1664[元記事へ]
白石和夫さんへのお返事です。
> 2005行と2065行を追加しました。
> 有理数モードで正しい答えになるようであれば,2000行と2050行の計算誤差が原因ではないでしょうか。
> 1480 IF bb=0 AND B(0)=0 THEN !IF b=0 THEN
1480 IF bb=0 AND ABS(B(0))<=1E-13 THEN !IF b=0 THEN
として対応します。
通常の整数の場合は、INT関数で0になるのでよいのですが、
多項式の場合は、「これに相当する処理がないため、有理数モードでの実行が前提となる」ということですね。
お騒がせしました。
|
|
|
戻る