a×b mod mは,BASICでは,MOD(a*b, m)です。
a*bが数値を正確に表現できる上限(10進モードだと16桁強)を超えないように注意します。
十進モードだと,a,b<1E8であれば大丈夫です。それを超えるときは有理数モードで計算してください。
an mod mをMOD(a^n,m)で計算すると,a^nが数値を正確に表現できる上限を超える可能性が高くなります。
たとえば,十進モードで
10 PRINT MOD(9^88,89) 20 END
を実行すると41になりますが,正しくは1です。有理数モードだと正しい答えが得られます。
法の数が1E8以下のときは,累乗を剰余系における乗算の繰り返しで計算すれば十進モードでも正しい値を求めることができます。
次のプログラムは十進モードでも正しい答えを計算します。
100 DECLARE FUNCTION PowerMod 110 PRINT PowerMod(9,88,89) 120 END 130 EXTERNAL FUNCTION PowerMod(a,n,m) 140 DECLARE NUMERIC x,i 150 LET x=1 160 FOR i=1 TO n 170 LET x=MOD(x*a,m) 180 NEXT i 190 LET PowerMod=x 200 END FUNCTION
しかし,繰り返し回数が多くなると時間がかかります。 p=99999989 として PowerMod(2,p-1,p) を計算すると十進モードで40秒ほどかかりました。
a2, a4, a8, a16, …は,2乗することの反復で素早く計算できます。
これを利用して,たとえば,a37=a1+4+32=a1a4a32と変型すれば累乗計算が高速化できます。
この計算法は,特に,剰余系での累乗を計算するのに有効です。次のプログラムはほぼ一瞬で答えを出します。
100 DECLARE FUNCTION PowerMod 110 LET p=99999989 120 PRINT PowerMod(2,p-1,p) 130 END 140 EXTERNAL FUNCTION PowerMod(a,n,m) 150 DECLARE NUMERIC x,i,y 160 LET x=1 170 LET y=a 180 DO WHILE n>0 190 IF MOD(n,2)=1 THEN LET x=MOD(x*y,m) 200 LET y=MOD(y^2,m) 210 LET n=INT(n/2) 220 LOOP 230 LET PowerMod=x 240 END FUNCTION
さらに桁数の大きい数を法としたいときは有理数モードで計算します。
100 OPTION ARITHMETIC RATIONAL 110 DECLARE FUNCTION PowerMod 120 LET a=2 130 LET p=2^32+1 140 PRINT PowerMod(a,p-1,p) 150 END 800 EXTERNAL FUNCTION PowerMod(a,n,m) 810 OPTION ARITHMETIC RATIONAL 820 DECLARE NUMERIC x,i,y 830 LET x=1 840 LET y=a 850 DO WHILE n>0 860 IF MOD(n,2)=1 THEN LET x=MOD(x*y,m) 870 LET y=MOD(y^2,m) 880 LET n=INT(n/2) 890 LOOP 900 LET PowerMod=x 910 END FUNCTION
p=232+1とすると,a=2のときap-1≡1 (mod p)となりますが,a=3だとap-1≡1 (mod p)とならないので,232+1は素数でないことがわかります(フェルマーの小定理による)。
100 OPTION ARITHMETIC RATIONAL 110 DECLARE EXTERNAL FUNCTION InvMod 120 DECLARE NUMERIC a,p 130 INPUT a,p 140 PRINT InvMod(a,p) 150 END 1000 EXTERNAL FUNCTION InvMod(a,m) 1010 OPTION ARITHMETIC RATIONAL 1020 DECLARE EXTERNAL FUNCTION Euclid 1030 DECLARE NUMERIC x,y,g 1040 CALL Euclid(a,m,x,y,g) 1050 ! ax+my=g, g=GCD(a,m) 1060 IF g<>1 THEN CAUSE EXCEPTION 999 1070 LET InvMod=MOD(x,m) 1080 END FUNCTION 2000 EXTERNAL SUB Euclid(a,b,x,y,g) 2010 OPTION ARITHMETIC RATIONAL 2020 DECLARE NUMERIC q,r,u,v 2030 LET q=INT(a/b) 2040 LET r=MOD(a,b) 2050 IF r=0 THEN 2060 LET x=0 2070 LET y=1 2080 LET g=b 2090 ELSE 2100 CALL Euclid(b,r,u,v,g) 2110 LET x=v 2120 LET y=u-q*v 2130 END IF 2140 END SUB