|
素数判定の関数PrimeQをベースにした関連の関数を実装してみました。
!n番目の素数 ※UBASIC prm(n)関数
FOR N=2 TO 168
PRINT N; Prime(N); N*LOG(N)+N*LOG(LOG(N)) !n番目の素数の近似
NEXT N
PRINT
!nより大きい素数の最小のもの ※UBASIC nxtprm(x)関数
FOR N=0 TO 100
PRINT N; NextPrime(N)
NEXT N
PRINT
!n以下の素数の数
LET N=1000
PRINT "素数は";PrimePi(N);"個です。"
PRINT N/LOG(N) !ガウス・アダマール・ピュイサンの素数定理による近似
PRINT N/(LOG(N)-1.08366) !ルジャンドルの近似
END
!試行割算法(6k±1)
EXTERNAL FUNCTION PrimeQ(n) !素数判定 1:素数、0:素数でない
LET PrimeQ=0
IF n<2 OR n<>INT(n) THEN EXIT FUNCTION !引数を確認する
!2以上の自然数なら
IF MOD(n,2)=0 THEN !2の倍数
IF n=2 THEN LET PrimeQ=1 !2は素数
ELSEIF MOD(n,3)=0 THEN !3の倍数
IF n=3 THEN LET PrimeQ=1 !3は素数
ELSE
LET k=5
DO WHILE k*k<=n !√nまで検証する
!+1,+3,+5は2の倍数(偶数)、+1,+4は3の倍数、+5は5の倍数
IF MOD(n,k)=0 THEN EXIT FUNCTION !5,11,17,23,29,35,41,47,…
IF MOD(n,k+2)=0 THEN EXIT FUNCTION !7,13,19,25,31,37,43,49,…
LET k=k+6
LOOP
LET PrimeQ=1 !最後まで割り切れなければ、素数である
END IF
END FUNCTION
EXTERNAL FUNCTION Prime(n) !n番目の素数
IF n<1 OR n<>INT(n) THEN EXIT FUNCTION !引数を確認する
IF n=1 THEN
LET Prime=2 !素数2
ELSEIF n=2 THEN
LET Prime=3 !素数3
ELSE
LET c=2 !見つけた個数
LET k=5
DO
!+1,+3,+5は2の倍数(偶数)、+1,+4は3の倍数、+5は5の倍数
IF PrimeQ(k)<>0 THEN
LET Prime=k
LET c=c+1 !5,11,17,23,29,… が素数なら
IF c=n THEN EXIT DO
END IF
IF PrimeQ(k+2)<>0 THEN
LET Prime=k+2
LET c=c+1 !7,13,19,25,31,…
IF c=n THEN EXIT DO
END IF
LET k=k+6 !次へ
LOOP
END IF
END FUNCTION
EXTERNAL SUB PrimeList(n,p()) !n個の素数列を返す
IF n<1 OR n<>INT(n) THEN EXIT SUB !引数を確認する
LET c=1 !見つけた個数
LET p(c)=2 !2は素数
IF n=1 THEN EXIT SUB
LET c=2
LET p(c)=3 !3は素数
IF n=2 THEN EXIT SUB
LET k=5
DO
IF PrimeQ(k)<>0 THEN !5,11,17,23,29,… が素数なら
LET c=c+1
LET p(c)=k
IF c=n THEN EXIT DO
END IF
IF PrimeQ(k+2)<>0 THEN !7,13,19,25,31,…
LET c=c+1
LET p(c)=k+2
IF c=n THEN EXIT DO
END IF
!+1,+3,+5は2の倍数(偶数)、+1,+4は3の倍数、+5は5の倍数
LET k=k+6 !次へ
LOOP
END SUB
EXTERNAL FUNCTION PrimePi(n) !n以下の素数の数
IF n<2 THEN
LET PrimePi=0 !見つけた個数
ELSEIF n<3 THEN
LET PrimePi=1 !見つけた個数
ELSEIF n<5 THEN
LET PrimePi=2 !見つけた個数
ELSE
LET c=2 !見つけた個数
LET k=5
DO
!+1,+3,+5は2の倍数(偶数)、+1,+4は3の倍数、+5は5の倍数
IF k>n THEN EXIT DO
IF PrimeQ(k)<>0 THEN LET c=c+1 !5,11,17,23,29,… が素数なら
IF k+2>n THEN EXIT DO
IF PrimeQ(k+2)<>0 THEN LET c=c+1 !7,13,19,25,31,…
LET k=k+6 !次へ
LOOP
LET PrimePi=c
END IF
END FUNCTION
EXTERNAL FUNCTION NextPrime(n) !nより大きい素数の最小のもの
IF n<2 THEN
LET NextPrime=2
ELSEIF n<3 THEN
LET NextPrime=3
ELSE
LET k=CEIL(n/6)*6 -1 !6m±1
DO
IF k>n THEN !見つかるまで
LET NextPrime=k
IF PrimeQ(k)<>0 THEN EXIT DO
END IF
IF k+2>n THEN !見つかるまで
LET NextPrime=k+2
IF PrimeQ(k+2)<>0 THEN EXIT DO
END IF
LET k=k+6 !次へ
LOOP
END IF
END FUNCTION
以下、サンプルです。 ただし、サブルーチン部分は省略します。
●素数階乗
FOR N=2 TO 30 !n#
LET S=1
LET i=2 !素数2
DO WHILE i<=N
LET S=S*i
LET i=NextPrime(i) !次の素数
LOOP
PRINT N;S
NEXT N
END
●区間[a,b]の素数の個数
LET A=1*10^7 ![a,b]
LET B=2*10^7
LET C=0
IF PrimeQ(A)<>0 THEN LET C=C+1 !aが素数
LET i=NextPrime(A)
DO WHILE i<=B
LET C=C+1
LET i=NextPrime(i)
LOOP
PRINT C;"個"
END
●区間篩い法
LET L=1*10^7 ![L,H]、1≦L≦H ※10^7以下
LET H=2*10^7
DIM F(L TO H) !篩い
MAT F=ZER
IF L=1 THEN LET F(1)=1 !1は素数でない
FOR J=2^2 TO H STEP 2 !素数2
IF J>=L THEN LET F(J)=1
NEXT J
LET i=3 !奇素数
DO WHILE i^2<=H !√hまで
FOR J=i^2 TO H STEP i*2
IF J>=L THEN LET F(J)=1
NEXT J
LET i=NextPrime(i)
LOOP
LET C=0
FOR i=L TO H
IF F(i)=0 THEN
LET C=C+1
!!!PRINT i !debug
END IF
NEXT i
PRINT C;"個"
END
●包除原理(個数定理)
LET N=10^6 !1からnまで
LET K=PrimePi(SQR(N)) !1から√nまでの素数を用意する
DIM P(K) !k個の素数列
CALL PrimeList(K,P)
LET NC=0
CALL try(1,1,1, N,K,P, NC)
PRINT NC+K-1;"個"
END
EXTERNAL SUB try(i,S,B, N,K,P(), C) !m個の素数の積による[n/p]
IF i=K+1 THEN
LET C=C+B*INT(N/S) ![n/s]
ELSE
CALL try(i+1,S,B, N,K,P, C) !ビットパターンが0のとき
LET T=S*P(i) !ビットパターンが1のとき
IF T<=N THEN CALL try(i+1,T,-B, N,K,P, C) !s>nのとき、[n/s]=0 と 昇順列 なので、これ以降は0となる
END IF
END SUB
|
|