=ここから=
option character kanji
input prompt "全角で1文字入力してください:":a$
let b=ord(a$)
let b$=str$(b)
let c$=bstr$(ord(a$),16)
let d$=right$(c$,2)&left$(c$,2)
print
print chr$(bval(c$,16))&"(JIS:"&c$&")"&" -> "&chr$(bval(d$,16))&"(JIS:"&d$&")"
end
=ここまで=
猶、例外が出る文字番地を一覧するもの書いてみました。
=ここから=
rem -- 全角文字の始点:8481 (2121) / 終端:38700 (972C) --
rem -- 結果出力は画面表示よりファイルに書き出した方が早いかも --
option arithmetic decimal
option character kanji
do
input prompt "どこから見る?(半角始点=1,全角始点=2)":start
if start=1 or start=2 then
exit do
elseif start=0 then
stop
else
end if
loop
select case start
case is =2
let start=8481
case else
end select
for count=start to 38700 step 1
let hcount$=bstr$(count,16)
let strcount$=str$(count)
when exception in
print chr$(39)+chr$(count)+chr$(39)+" chr$("+strcount$+") <-> JIS ["+hcount$+"]"
use
print chr$(7)+"例外"+str$(extype)+chr$(7)+" chr$("+strcount$+") <-> JIS ["+hcount$+"]"
end when
next count
end
=ここまで=
Windows XP (Windows2000) は文字コードがユニコードに変更されています。
シフトJISの文字はユニコードに変換されて表示されます。
シフトJISとJISの対応は,一応,一対一とみなせますが,
ユニコードとJIS(あるいはシフトJIS)との対応は一対一ではありません。
シフトJIS→ユニコード→シフトJISと変換すると元に戻らないことがあります。
十進BASICの場合,ファイル入出力はシフトJISなので,
画面に表示した文字をクリップボード経由で取り出すのでなく,
ファイルに書き出した文字を対象にすれば,問題は起こりにくくなると思います。
100 OPTION CHARACTER KANJI
110 INPUT PROMPT "全角で1文字入力してください:":a$
120 LET b=ORD(a$)
130 LET b$=STR$(b)
140 LET c$=BSTR$(ORD(a$),16)
150 LET d$=right$(c$,2)&left$(c$,2)
160 PRINT
170 PRINT CHR$(BVAL(c$,16))&"(JIS:"&c$&")"&" -> "&CHR$(BVAL(d$,16))&"(JIS:"&d$&")"
180 OPEN #1:NAME "A:TEST.TXT"
190 ERASE #1
200 PRINT #1:CHR$(BVAL(d$,16))
210 CLOSE #1
220 OPEN #2:NAME "A:TEST.TXT"
230 INPUT #2:s$
240 CLOSE #2
250 PRINT BSTR$(ORD(s$),16)
260 END
100 OPTION ARITHMETIC DECIMAL
110 OPTION CHARACTER KANJI
120 FOR hi=BVAL("21",16) TO BVAL("73",16)
130 FOR lo=BVAL("21",16) TO BVAL("7E",16)
140 LET count=hi*256+lo
150 LET hcount$=BSTR$(count,16)
160 LET strcount$=STR$(count)
170 WHEN EXCEPTION IN
180 PRINT
CHR$(39)&CHR$(count)&CHR$(39)&" chr$("&strcount$&")
<-> JIS ["&hcount$&"]"
190 USE
200 PRINT
CHR$(7)&"例外"&STR$(EXTYPE)&CHR$(7)&"
chr$("&strcount$&") <-> JIS ["&hcount$&"]"
210 END WHEN
220 NEXT lo
230 NEXT hi
240 END
FUNCTION GCD(a,b) !最大公約数
IF b=0 THEN LET GCD=a ELSE LET GCD=GCD(b, MOD(a,b))
END FUNCTION
LET r1=8 !固定円の半径
LET r2=5 !動く円の半径 ※r1*r2>0なら内側、r1*r2<0なら外側
LET r3=4 !点Pの位置(動く円の中心から) ※r3=r2ならサイクロイド、r3≠r2ならトロコイド
!LET r1=8 !固定円の直径 r1:r2=2:1
!LET r2=4
!LET r3=r2
!LET r1=12 !アステロイド 4:1
!LET r2=3
!LET r3=r2
!LET r1=5 !カージオイド 1:1
!LET r2=-5
!LET r3=ABS(r2)
!LET r1=4 !ネフロイド 2:1
!LET r2=-2
!LET r3=ABS(r2)
IF r1*r2>0 THEN
IF ABS(r1)>ABS(r2) THEN
LET sz=MAX(ABS(r1),ABS(r1-r2)+ABS(r3))+1
ELSE
LET sz=ABS(r1)+ABS(r3)+1
END IF
ELSE
LET sz=ABS(r1)+ABS(r2)+ABS(r3)+1
END IF
SET WINDOW -sz,sz,-sz,sz !表示領域
DRAW grid !座標
DRAW circle WITH SCALE(r1) !大きな円
LET iter=r2/GCD(r1,r2) !周回数
SET DRAW MODE NOTXOR
DIM w(4,4) !ローカル座標をワールド座標に変換する
MAT w=SHIFT(r1-r2,0) !1つ前
DRAW p(0) WITH w
FOR th=0 TO 360*iter !STEP 0.2 !※疎になるなら調整
DRAW p(0) WITH w !1つ前を消す
MAT w=ROTATE(-r1/r2*RAD(th)) * SHIFT(r1-r2,0)*ROTATE(RAD(th)) !姿勢と位置
DRAW p(1) WITH w !ワールド座標に、動く円と点Pを描く
WAIT DELAY 0.02
NEXT th
PICTURE p(f) !ローカル座標の原点を基準に、動く円と点Pを描く
IF f=1 THEN !描画順を考慮して、先に点Pを描く
SET DRAW MODE OVERWRITE !描画diskにNOTXORを反映させない
DRAW disk WITH SCALE(0.2)*SHIFT(r3,0)
SET DRAW MODE NOTXOR
END IF
DRAW circle WITH SCALE(r2) !動く円
PLOT LINES: 0,0; r3,0
END PICTURE
REM ** 画像縮小補正プログラム **
OPTION ARITHMETIC NATIVE
DECLARE EXTERNAL SUB revision1,revision2
GLOAD "C:\Program Files\Decimal BASIC\BASICw32\SAMPLE\ZENKOUJI.JPG"
LET px0=PIXELX(1)
LET py0=PIXELY(1)
SET WINDOW 0,px0,0,py0
DIM pict0(0 TO px0,0 TO py0) ! 元画像(配列の下限は0以外も可)
SET COLOR MODE "NATIVE"
ASK PIXEL ARRAY (0,py0) pict0 ! 元画像の色指標
DO
LET err=0
INPUT PROMPT "[縮小率入力] 分子,分母 (分子=1 or 分子=分母-1)" : num,denom
IF num<1 OR INT(num)<>num THEN LET err=1
IF denom<2 OR INT(denom)<>denom THEN LET err=1
IF num<>1 AND num<>denom-1 THEN LET err=1
LOOP UNTIL err=0
LET t0=TIME
LET kk=num/denom ! 縮小率
MAT PLOT CELLS, IN px0-px0*kk,py0*kk ; px0,0 : pict0 !! 補正なし
!
LET px9=INT(SIZE(pict0,1)*kk+0.00001)-1 ! k=1/3,3*k<>1に対応
LET py9=INT(SIZE(pict0,2)*kk+0.00001)-1
DIM pict9(0 TO px9,0 TO py9) ! 縮小補正画像(配列の下限は0)
IF num=1 THEN
CALL revision1(pict0,pict9,denom) ! 縮小率=1/n
ELSE
CALL revision2(pict0,pict9,denom) ! 縮小率=(n-1)/n
END IF
IF TIME-t0<0.2 THEN WAIT DELAY 0.2
BEEP
SET TEXT COLOR "RED"
SET TEXT HEIGHT py0/30
PLOT TEXT ,AT 1,1 : "PUSH ANY KEY"
DO
FOR i=8 TO 239
IF GetKeyState(i)<0 THEN EXIT DO
NEXT i
LOOP
MAT PLOT CELLS, IN 0,py9 ; px9,0 : pict9 !! 補正あり
BEEP
END
REM 縮小率=1/n (1/2,1/3,1/4,...)
EXTERNAL SUB revision1(sp0(,),sp9(,),k)
OPTION ARITHMETIC NATIVE
LET kk=1/k
DIM c9(3)
LET lx0=LBOUND(sp0,1)
LET ly0=LBOUND(sp0,2)
LET ux0=UBOUND(sp0,1)
LET uy0=UBOUND(sp0,2)
LET ux9=UBOUND(sp9,1)
LET uy9=UBOUND(sp9,2)
FOR i=lx0 TO ux0-(k-1) STEP k
FOR j=ly0 TO uy0-(k-1) STEP k
MAT c9=ZER
FOR ii=0 TO k-1
FOR jj=0 TO k-1
CALL acm(i+ii,j+jj)
NEXT jj
NEXT ii
LET sp9((i-lx0)*kk,(j-ly0)*kk)=COLORINDEX(c9(1)/k^2,c9(2)/k^2,c9(3)/k^2)
NEXT j
NEXT i
LET rm2=MOD(uy0,k) ! 縁(横)の処理
IF rm2<>k-1 THEN
FOR i=lx0 TO ux0-(k-1) STEP k
MAT c9=ZER
FOR j=0 TO rm2
CALL acm(i,uy0-j)
NEXT j
LET sp9((i-lx0)*kk,uy9)=COLORINDEX(c9(1)/(rm2+1),c9(2)/(rm2+1),c9(3)/(rm2+1))
NEXT i
END IF
LET rm1=MOD(ux0,k) ! 縁(縦)の処理
IF rm1<>k-1 THEN
FOR j=ly0 TO uy0-(k-1) STEP k
MAT c9=ZER
FOR i=0 TO rm1
CALL acm(ux0-i,j)
NEXT i
LET sp9(ux9,(j-ly0)*kk)=COLORINDEX(c9(1)/(rm1+1),c9(2)/(rm1+1),c9(3)/(rm1+1))
NEXT j
END IF
IF rm1<>k-1 OR rm2<>k-1 THEN ! 角の処理
MAT c9=ZER
FOR i=0 TO rm1
FOR j=0 TO rm2
CALL acm(ux0-i,uy0-j)
NEXT j
NEXT i
LET rm12=(rm1+1)*(rm2+1)
LET sp9(ux9,uy9)=COLORINDEX(c9(1)/rm12,c9(2)/rm12,c9(3)/rm12)
END IF
SUB acm(x0,y0)
ASK COLOR MIX(sp0(x0,y0)) b,g,r
LET c9(1)=c9(1)+b
LET c9(2)=c9(2)+g
LET c9(3)=c9(3)+r
END SUB
END SUB
REM 縮小率=(n-1)/n (2/3,3/4,4/5,...)
EXTERNAL SUB revision2(sp0(,),sp9(,),k)
OPTION ARITHMETIC NATIVE
DECLARE FUNCTION c_ave
LET kk=(k-1)/k
LET num1=(k-1)-1
LET lx0=LBOUND(sp0,1)
LET ly0=LBOUND(sp0,2)
LET ux0=UBOUND(sp0,1)
LET uy0=UBOUND(sp0,2)
LET ux9=UBOUND(sp9,1)
LET uy9=UBOUND(sp9,2)
FOR i=lx0 TO ux0-k STEP k
FOR j=ly0 TO uy0-k STEP k
CALL center
CALL side1(i,j,1,0)
CALL side1(i+k,j,-1,num1)
CALL side2(i,j,1,0)
CALL side2(i,j+k,-1,num1)
CALL corner(i,j,1,1,0,0)
CALL corner(i,j+k,1,-1,0,num1)
CALL corner(i+k,j,-1,1,num1,0)
CALL corner(i+k,j+k,-1,-1,num1,num1)
NEXT j
NEXT i
LET x8=(i-lx0-k)*kk+num1
LET y8=(j-ly0-k)*kk+num1
IF uy9<>y8 THEN CALL edge1
IF ux9<>x8 THEN CALL edge2
IF ux9<>x8 AND uy9<>y8 THEN CALL edge_corner
FUNCTION c_ave(c1,c2) ! 色強度加重平均
ASK COLOR MIX(c1) b1,g1,r1
ASK COLOR MIX(c2) b2,g2,r2
LET c_ave=COLORINDEX((b1+2*b2)/3,(g1+2*g2)/3,(r1+2*r2)/3)
END FUNCTION
SUB center
FOR ii=2 TO num1
FOR jj=2 TO num1
LET sp9((i-lx0)*kk+ii-1,(j-ly0)*kk+jj-1)=sp0(i+ii,j+jj)
NEXT jj
NEXT ii
END SUB
SUB side1(x,y,ii,m)
FOR jj=2 TO num1
LET sp9((i-lx0)*kk+m,(j-ly0)*kk+jj-1)=c_ave(sp0(x,y+jj),sp0(x+ii,y+jj))
NEXT jj
END SUB
SUB side2(x,y,jj,n)
FOR ii=2 TO num1
LET sp9((i-lx0)*kk+ii-1,(j-ly0)*kk+n)=c_ave(sp0(x+ii,y),sp0(x+ii,y+jj))
NEXT ii
END SUB
SUB corner(x,y,ii,jj,m,n)
ASK COLOR MIX(sp0(x,y)) b1,g1,r1
ASK COLOR MIX(sp0(x,y+jj)) b2,g2,r2
ASK COLOR MIX(sp0(x+ii,y)) b3,g3,r3
ASK COLOR MIX(sp0(x+ii,y+jj)) b4,g4,r4
LET bb=(b1+2*b2+2*b3+4*b4)/9
LET gg=(g1+2*g2+2*g3+4*g4)/9
LET rr=(r1+2*r2+2*r3+4*r4)/9
LET sp9((i-lx0)*kk+m,(j-ly0)*kk+n)=COLORINDEX(bb,gg,rr)
END SUB
SUB edge1
FOR i=lx0 TO ux0-k STEP k ! 下辺の処理
FOR ii=0 TO num1
FOR jj=0 TO uy9-y8-2
LET sp9((i-lx0)*kk+ii,uy9-jj)=sp0(i+ii+1,uy0-jj)
NEXT jj
LET sp9((i-lx0)*kk+ii,uy9-jj)=c_ave(sp0(i+ii+1,uy0-(jj+1)),sp0(i+ii+1,uy0-jj))
NEXT ii
NEXT i
END SUB
SUB edge2
FOR j=ly0 TO uy0-k STEP k ! 右辺の処理
FOR jj=0 TO num1
FOR ii=0 TO ux9-x8-2
LET sp9(ux9-ii,(j-ly0)*kk+jj)=sp0(ux0-ii,j+jj+1)
NEXT ii
LET sp9(ux9-ii,(j-ly0)*kk+jj)=c_ave(sp0(ux0-(ii+1),j+jj+1),sp0(ux0-ii,j+jj+1))
NEXT jj
NEXT j
END SUB
SUB edge_corner
FOR ii=ux9 TO x8+1 STEP-1
FOR jj=uy9 TO y8+1 STEP-1
LET sp9(ii,jj)=sp0(ux0-(ux9-ii),uy0-(uy9-jj))
NEXT jj
NEXT ii
END SUB
END SUB
FUNCTION phi(k,i,N) !基底関数φk(i)
IF k=0 THEN
LET phi=1/SQR(N)
ELSE
LET phi=SQR(2/N)*COS((2*i+1)*k*PI/(2*N))
END IF
END FUNCTION
SUB DCT(f(,),TBL(,),iTBL(,), FF(,)) !DCT変換
MAT FF=TBL*f
MAT FF=FF*iTBL !F(k,l)=Σ[j=0,N-1]Σ[i=0,N-1]f(i,j)*φk(i)*φl(j)
END SUB
SUB iDCT(FF(,),TBL(,),iTBL(,), f(,)) !DCT逆変換
MAT f=iTBL*FF
MAT f=f*TBL !f(i,j)=Σ[l=0,N-1]Σ[k=0,N-1]F(k,l)*φk(i)*φl(j)
END SUB
DIM TBLn(0 TO N-1,0 TO N-1) !変換行列 T
MAT TBLn=ZER
FOR k=0 TO N-1 !N×Nブロックのφk(i)のテーブルをつくる
FOR i=0 TO N-1
LET TBLn(k,i)=phi(k,i,N)
NEXT i
NEXT k
!!!MAT PRINT TBLn;
DIM iTBLn(N,N) !※T^-1=T^t、∵ユニタリー行列
MAT iTBLn=TRN(TBLn)
!-------------------- ここまでがサブルーチン
SET COLOR MODE "NATIVE"
!GLOAD "c:\BASICw32\SAMPLE\ZENKOUJI.JPG" !画像を読み込む
GLOAD "c:\My Documents\test2.bmp" !画像を読み込む
ASK PIXEL SIZE (0,0; 1,1) w,h !画像の縦横の大きさ(ピクセル単位)を調べる
DIM p(w,h) !画像の大きさに対応する配列要素を用意する
ASK PIXEL ARRAY (0,1) p !画像の各点の色情報を配列に格納する
PRINT "画像の大きさ 縦:";h;" 横:";w
!SET BITMAP SIZE w,h !ウィンドウの大きさを画像に合わせる
LET A=5 !拡大縮小率 A/N
!LET A=11 !拡大縮小率
LET ww=INT(w*A/N+0.5) !変換後の画像の大きさ
LET hh=INT(h*A/N+0.5)
PRINT A;"/";N;"倍(縦横比は固定) 縦:";hh;" 横:";ww
IF ww<=0 OR hh<=0 THEN
PRINT "画像の大きさが0または負になります。"
STOP
END IF
DIM q(ww,hh) !変換後の画像を格納する配列
LET t0=TIME
DIM TBLa(0 TO A-1,0 TO A-1)
MAT TBLa=ZER
FOR k=0 TO A-1 !A×Aブロックのφk(i)のテーブルをつくる
FOR i=0 TO A-1
LET TBLa(k,i)=phi(k,i,A)
NEXT i
NEXT k
DIM iTBLa(0 TO A-1,0 TO A-1)
MAT iTBLa=TRN(TBLa)
FOR by=0 TO INT((h-1)/N) !ブロック単位に分割する
FOR bx=0 TO INT((w-1)/N)
FOR j=1 TO N !ブロック内の画像
LET y=by*N+j
IF y>h THEN EXIT FOR !下端なら
FOR i=1 TO N
LET x=bx*N+i
IF x>w THEN EXIT FOR !右端なら
!!!PRINT x;y,i;j
LET c=p(x,y)
ASK COLOR MIX(c) r,g,b !RGBを取得する
DIM Br(N,N),Bg(N,N),Bb(N,N) !画素の色濃度 ※画像信号 f(i,j)
LET Br(i,j)=r
LET Bg(i,j)=g
LET Bb(i,j)=b
NEXT i
NEXT j
!※縮小なら高周波成分の行と列を除く、拡大なら不足部分は0を補う
DIM Tr(A,A),Tg(A,A),Tb(A,A)
IF A>N THEN !拡大なら
MAT Tr=ZER(A,A)
MAT Tg=ZER(A,A)
MAT Tb=ZER(A,A)
END IF
FOR j=1 TO MIN(N,A) !copy it
FOR i=1 TO MIN(N,A)
LET Tr(i,j)=BVr(i,j)
LET Tg(i,j)=BVg(i,j)
LET Tb(i,j)=BVb(i,j)
NEXT i
NEXT j
DEF ha(f)=MOD(f,cEps*10) !評価関数
SUB hatch(t, x,y,c) !ハッチ形状なら点(x,y)を描く
LET flg=0
IF (t=1 OR t=5) AND ha(y)<cEps THEN LET flg=1 !横
IF (t=2 OR t=5) AND ha(x)<cEps THEN LET flg=1 !縦
IF (t=3 OR t=6) AND ha(x+y)<cEps THEN LET flg=1 !左斜め
IF (t=4 OR t=6) AND ha(x-y)<cEps THEN LET flg=1 !右斜め
IF t=0 OR flg=1 THEN !t=0はベタ塗り
SET POINT COLOR c
PLOT POINTS: x,y
END IF
END SUB
!条件を満たす領域を描く
SET POINT STYLE 1 !ドット形式
FOR j=1 TO h !画面全体を走査する
LET y=WORLDY(j) !ドットをxy座標に変換する
FOR i=1 TO w
LET x=WORLDX(i)
WHEN EXCEPTION IN
!不等式が示す領域 ※y>f(x)はf(x)>0、y<f(x)はf(x)<0を意味する
IF y>f(x) THEN CALL hatch(4, x,y,4) !条件を満たすなら
IF g(x,y)<0 THEN CALL hatch(3, x,y,2)
!連立不等式が示す領域
!IF y>f(x) AND g(x,y)<0 THEN CALL hatch(5, x,y,2) !条件を満たすなら
USE
END WHEN
NEXT i
NEXT j
!曲線を描く ※y=f(x)
FOR x=a TO b STEP cEps
WHEN EXCEPTION IN
PLOT LINES: x,f(x); !折れ線で近似する
USE
PLOT LINES
END WHEN
NEXT x
PLOT LINES
PLOT TEXT ,AT -2,4: "f(x)"
!曲線を描く ※連続なf(x,y)=0
SET POINT COLOR 1
FOR y=c TO d STEP cEps
LET x=a
LET z=g(x,y)
FOR x=a TO b STEP cEps
LET z0=z
LET z=g(x,y)
IF z0*z<0 THEN PLOT POINTS: x,y !符号が変われば
NEXT x
NEXT y
PLOT TEXT ,AT -3,-3: "g(x)"
IF X <= 10 THEN PRINT USING "<###" : 123
IF X <> 10 THEN PRINT USING "<%%%" : 123
IF X<=10 THEN PRINT USING "<###":123
IF X<>10 THEN PRINT USING "<%%%":123
PRINT USING "#<" : w10, w1
PRINT USING "#<":w10, w1
と書いたとする。
IF X <= 10 THEN PRINT USING "<###" : 123
IF X <> 10 THEN PRINT USING "<%%%" : 123
IF X<=10 THEN PRINT USING "<###":123
IF X<>10 THEN PRINT USING "<%%%":123
PRINT USING "#<" : w10, w1
PRINT USING "#<":w10, w1
DIM CC(K) !定数 (1 1 1 …)
MAT CC=CON
DIM BB(K) !定数 (1 10 100 …)
FOR i=1 TO K
LET BB(i)=10^(i-1) !位
NEXT i
DIM V(K) !ベクトル
FOR k2=0 TO 9 !十の位
LET V(2)=k2
FOR k1=0 TO 9 !一の位
LET V(1)=k1
IF MOD(DOT(V,CC),3)=0 THEN !各桁の和が3の倍数なら
PRINT DOT(V,BB) !x=k1+k2*10+k3*100+ …
ELSEIF V(1)=3 OR V(2)=3 THEN !いずれかが3となる
PRINT DOT(V,BB) !x=k1+k2*10+k3*100+ …
END IF
FUNCTION tr(A(,)) !行列Aのトレース
LET t=0 !対角成分の和
FOR m=1 TO MIN(UBOUND(A,1),UBOUND(A,2))
LET t=t+A(m,m)
NEXT m
LET tr=t
END FUNCTION
LET K=4 !桁数
DIM B(K,1) !定数 t[1 10 100 …]
FOR i=1 TO K
LET B(i,1)=10^(i-1) !位
NEXT i
DIM C(1,K) !定数 [1 1 1 …]
MAT C=CON
DIM TT(K,1),X(1,1) !作業用
DIM A(K,K) !対角行列
MAT A=ZER
FOR k2=0 TO 9 !十の位
LET A(2,2)=k2
FOR k1=0 TO 9 !一の位
LET A(1,1)=k1
IF MOD(tr(A),3)=0 THEN !各桁の和が3の倍数なら
MAT TT=A*B !x=k1+k2*10+k3*100+ …
MAT X=C*TT
MAT PRINT X; !PRINT X(1,1)
ELSEIF A(1,1)=3 OR A(2,2)=3 THEN !いずれかが3となる
MAT TT=A*B !x=k1+k2*10+k3*100+ …
MAT X=C*TT
MAT PRINT X;
END IF
PUBLIC NUMERIC ANSWER_COUNT !解答数
LET ANSWER_COUNT=0
PUBLIC STRING num$
LET num$="0123456789ABCDEF" !N進法の数字
DIM M(0 TO N-1,0 TO N-1) !平方の方陣
MAT M=(-1)*CON
SET WINDOW -1,N+1,N+1,-1
DRAW grid
LET t0=TIME
CALL BackTrack(N,M,0) !左上から
PRINT "計算時間=";TIME-t0
END
EXTERNAL SUB BackTrack(N,M(,),p) !(左上からの連番)位置pを調査する
IF p<N*N THEN !すべてが埋まるまで
LET row=INT(p/N) !行と列に換算する
LET col=MOD(p,N)
FOR k=0 TO N*N-1 !0〜N*N-1範囲の数字を
CALL CheckRule(N,M, row,col,k, rc)!矛盾なく置ければ
IF rc=1 THEN
SET TEXT COLOR 1
PLOT TEXT ,AT col+0.5,row+0.5: STR$(k)
LET M(row,col)=k !ここに置いてみる
CALL BackTrack(N,M,p+1) !次へ
LET M(row,col)=-1 !取り消す
SET TEXT COLOR 0
PLOT TEXT ,AT col+0.5,row+0.5: STR$(k)
END IF
NEXT k
ELSE !すべて埋まったら
LET ANSWER_COUNT=ANSWER_COUNT+1 !解答数
PRINT ANSWER_COUNT
FOR i=0 TO N-1
FOR j=0 TO N-1
LET t=M(i,j)
LET k1=MOD(t,N)+2 !N進法での各桁の値(文字位置を加味)
LET k2=INT(t/N)+2
PRINT num$(k2:k2); num$(k1:k1); " "; !解を表示する
NEXT j
PRINT
NEXT i
PRINT
END IF
END SUB
EXTERNAL SUB CheckRule(N,M(,), row,col,K, rc) !同じ数があるかどうか確認する
LET rc=0
FOR y=0 TO N-1 !埋まっている範囲で未使用の数字か
FOR x=0 TO N-1
IF y>=row AND x>=col THEN EXIT FOR
IF M(y,x)=K THEN EXIT SUB !見つかったので、NG!
NEXT x
NEXT y
LET k1=MOD(K,N) !N進法での1桁目
LET k2=INT(K/N) !N進法での2桁目
FOR y=0 TO row-1 !列
LET t=M(y,col)
IF MOD(t,N)=k1 THEN EXIT SUB
IF INT(t/N)=k2 THEN EXIT SUB
NEXT y
FOR x=0 TO col-1 !行
LET t=M(row,x)
IF MOD(t,N)=k1 THEN EXIT SUB
IF INT(t/N)=k2 THEN EXIT SUB
NEXT x
PUBLIC STRING num$
LET num$="0123456789ABCDEF" !N進法の数字
DIM M(0 TO N*N-1) !平方の方陣
MAT M=(-1)*CON
FOR i=0 TO N-1 !標準形の場合 ※1行目と1列目が整列している
LET M(i*N+0)=i
LET M(0*N+i)=i
NEXT i
LET t0=TIME
CALL BackTrack(N,M,0) !左上から
PRINT "計算時間=";TIME-t0
END
EXTERNAL SUB BackTrack(N,M(),p) !(左上からの連番)位置pを調査する
IF p<N*N THEN !すべてが埋まるまで
IF M(p)>=0 THEN !既に置いてあれば
CALL BackTrack(N,M,p+1) !次へ
ELSE
FOR k=0 TO N-1 !数字0〜N-1を
CALL CheckRule(N,M, p,k, rc)!矛盾なく置ければ
IF rc=1 THEN
LET M(p)=k !ここに置いてみる
CALL BackTrack(N,M,p+1) !次へ
LET M(p)=-1 !取り消す
END IF
NEXT k
END IF
ELSE !すべて埋まったら
LET CntOfLM=CntOfLM+1 !解答数
PRINT CntOfLM
FOR i=0 TO N-1
FOR j=0 TO N-1
LET t=M(i*N+j)+1
PRINT num$(t+1:t+1); " "; !解を表示する
NEXT j
PRINT
NEXT i
PRINT
END IF
END SUB
EXTERNAL SUB CheckRule(N,M(), p,K, rc) !同じ数があるかどうか確認する
LET rc=0
LET row=INT(p/N) !行と列に換算する
LET col=MOD(p,N)
FOR i=0 TO row-1 !列
IF M(i*N+col)=K THEN EXIT SUB
NEXT i
FOR i=0 TO col-1 !行
IF M(row*N+i)=K THEN EXIT SUB
NEXT i
!※N=1,2,3,4,5,6,7,…なら、1,1,1,4,56,9408,16942080,…となる。
PUBLIC NUMERIC LM(9408,0 TO 35) !標準形ラテン方陣 N=6
PUBLIC NUMERIC CntOfLM !その数
LET CntOfLM=0
DIM M(0 TO N*N-1) !平方の方陣
MAT M=(-1)*CON
FOR i=0 TO N-1 !標準形 ※1行目と1列目が整列している
LET M(i*N+0)=i
LET M(0*N+i)=i
NEXT i
LET t0=TIME
CALL BackTrack(N,M,0) !左上から
PRINT CntOfLM
PRINT "計算時間=";TIME-t0
LET t0=TIME
PUBLIC NUMERIC ANSWER_COUNT !解答数
LET ANSWER_COUNT=0
LET cnt=0 !検証回数
LET cc=comb(CntOfLM+2-1,2)
DIM A(0 TO N-1,0 TO N-1),B(0 TO N-1,0 TO N-1)
FOR i=1 TO CntOfLM !標準形Aと標準形Bの展開との重複組合せ 56H2
FOR y=0 TO N-1 !Aを指定する
FOR x=0 TO N-1
LET A(y,x)=LM(i,y*N+x)
NEXT x
NEXT y
FOR j=i TO CntOfLM
LET cnt=cnt+1 !進捗
PRINT cnt;"/";cc
FOR y=0 TO N-1 !Bを指定する
FOR x=0 TO N-1
LET B(y,x)=LM(j,y*N+x)
NEXT x
NEXT y
DIM R(N) !順列の初期値
FOR k=1 TO N
LET R(k)=k
NEXT k
CALL RPerm(N,A,B, R,2) !まず行順を指定する ※1行目は固定
NEXT j
NEXT i
IF ANSWER_COUNT=0 THEN PRINT "解なし"
PRINT "計算時間=";TIME-t0
END
EXTERNAL SUB BackTrack(N,M(),p) !(左上からの連番)位置pを調査する
IF p<N*N THEN !すべてが埋まるまで
IF M(p)>=0 THEN !既に置いてあれば
CALL BackTrack(N,M,p+1) !次へ
ELSE
FOR k=0 TO N-1 !数字0〜N-1を
CALL CheckRule(N,M, p,k, rc)!矛盾なく置ければ
IF rc=1 THEN
LET M(p)=k !ここに置いてみる
CALL BackTrack(N,M,p+1) !次へ
LET M(p)=-1 !取り消す
END IF
NEXT k
END IF
ELSE !すべて埋まったら
LET CntOfLM=CntOfLM+1 !数と配置を記録する
FOR i=0 TO N*N-1
LET LM(CntOfLM,i)=M(i)
NEXT i
END IF
END SUB
EXTERNAL SUB CheckRule(N,M(), p,K, rc) !同じ数があるかどうか確認する
LET rc=0
LET row=INT(p/N) !行と列に換算する
LET col=MOD(p,N)
FOR i=0 TO row-1 !列
IF M(i*N+col)=K THEN EXIT SUB
NEXT i
FOR i=0 TO col-1 !行
IF M(row*N+i)=K THEN EXIT SUB
NEXT i
LET rc=1 !見つからないので、OK!
END SUB
EXTERNAL SUB RPerm(N,A(,),B(,), P(),i) !順列を生成して行の並び替え ※辞書式順ではない
IF I<N THEN
FOR j=i TO N
LET t=P(i) !i番目とj番目を交換する
LET P(i)=P(j)
LET P(j)=t
CALL RPerm(N,A,B, P,i+1) !再帰呼出し
LET t=P(i) !元に戻す
LET P(i)=P(j)
LET P(j)=t
NEXT j
ELSE !完了なら
DIM C(N) !順列の初期値
FOR j=1 TO N
LET C(j)=j
NEXT j
CALL CPerm(N,A,B,P,C,1) !今度は列順を指定する
END IF
END SUB
EXTERNAL SUB CPerm(N,A(,),B(,),R(), P(),i) !順列を生成して列の並び替え ※辞書式順ではない
IF I<N THEN
FOR j=i TO N
LET t=P(i) !i番目とj番目を交換する
LET P(i)=P(j)
LET P(j)=t
CALL CPerm(N,A,B,R, P,i+1) !再帰呼出し
LET t=P(i) !元に戻す
LET P(i)=P(j)
LET P(j)=t
NEXT j
ELSE !オイラー方陣をつくって検証する
DIM EM(N,N) !使用できる数字の組と使用状況
MAT EM=ZER
!※ラテン方陣の組合せなので、行と列の重複はない。
FOR i=0 TO N-1 !方陣全体で同じ数があるかどうか確認する
FOR j=0 TO N-1
LET rr=A(i,j)+1 !オイラー方陣をつくる
LET cc=B(R(i+1)-1,P(j+1)-1)+1
IF EM(rr,cc)=1 THEN EXIT SUB !その数字は使用中なのでNG!
LET EM(rr,cc)=1
NEXT j
NEXT i
LET ANSWER_COUNT=ANSWER_COUNT+1 !解答数
PRINT ANSWER_COUNT
FOR i=0 TO N-1 !答えを表示する
FOR j=0 TO N-1
PRINT (A(i,j)+1)*10 + B(R(i+1)-1,P(j+1)-1)+1 ;
NEXT j
PRINT
NEXT i
OPTION BASE 0
LET N= 3 ! 2,3,4,5,6
DIM lb(9408,N,N) ! N=1〜7: 1,1,1,4,56,9408,16942080 N=7は非現実的
DIM wb(N,N), xidx(N), yidx(N), fb(N,N)
!
CALL main
SUB makelb(x, y)
local i,j
FOR i=0 TO N-1
FOR j=0 TO x-1
IF i=wb(y,j) THEN EXIT FOR ! break;
NEXT j
IF j>x-1 THEN
FOR j=0 TO y-1
IF i=wb(j,x) THEN EXIT FOR ! break;
NEXT j
IF j>y-1 THEN
LET wb(y,x)= i
IF y=N-1 AND x=N-1 THEN
!----memcpy(lb[lbs++], wb, sizeof(wb));
FOR a=0 TO N
FOR b=0 TO N
LET lb(lbs,a,b)=wb(a,b)
NEXT b
NEXT a
LET lbs=lbs+1
!---------------
EXIT SUB ! return;
END IF
IF
y=N-1 THEN CALL makelb(x+1, 1) ELSE CALL makelb((x),y+1)
END IF
END IF
NEXT i
END SUB
SUB echk
local i,j
MAT fb=ZER ! memset(fb, 0, sizeof(fb));
FOR i= 0 TO N-1
FOR j= 0 TO N-1
IF fb( lb(p,i,j), lb(q,yidx(i),xidx(j)) )>0 THEN EXIT SUB ! return;
LET fb( lb(p,i,j), lb(q,yidx(i),xidx(j)) )=1
NEXT j
NEXT i
FOR i= 0 TO N-1
FOR j= 0 TO N-1
PRINT USING "%#": lb(p,i,j)+1, lb(q,yidx(i),xidx(j))+1;
IF j=N-1 THEN PRINT ELSE PRINT " ";
NEXT j
NEXT i
STOP ! exit(0);
END SUB
SUB check1(n_)
local i
FOR i=n_ TO N-1
swap xidx(i),xidx(n_)
!-----check2(n_)
local i_
FOR i_= n_ TO N-1
swap yidx(i_),yidx(n_)
IF ( yidx(n_)<>xidx(n_)) AND (n_<>1 OR yidx(n_)< xidx(n_) ) THEN
IF n_=N-1 THEN CALL echk ELSE CALL check1(n_+1)
END IF
swap yidx(i_),yidx(n_)
NEXT i_
!------
swap xidx(i),xidx(n_)
NEXT i
END SUB
SUB main
FOR i= 0 TO N-1
LET wb(i,0)= i
LET wb(0,i)= i
NEXT i
LET lbs = 0
PRINT "N=";N; ! 追加した表示
CALL makelb(1,1)
PRINT "lbs=";lbs !追加
MAT PRINT wb ! 追加
LET count= 0
FOR p=0 TO lbs-1
FOR q=p TO lbs-1
LET count=count+1
IF MOD(count,1000)=0 THEN PRINT count
FOR i= 0 TO N-1
LET yidx(i)= i
LET xidx(i)= i
NEXT i
CALL check1(1)
NEXT q
NEXT p
PRINT "解は見つかりませんでした."
END SUB
SUB dec(C(),p, w) !パケット内上からp位置のカードを削除する
LET w=C(p)
FOR i=p TO C(0)-1 !前に詰める
LET C(i)=C(i+1)
NEXT i
LET C(0)=C(0)-1
END SUB
SUB inc(C(),p,w) !パケット内上からp位置にカードを追加する
IF p<=C(0) THEN
FOR i=C(0) TO p STEP -1 !後ろにずらす
LET C(i+1)=C(i)
NEXT i
ELSE
LET p=C(0)+1 !最後
END IF
LET C(p)=w
LET C(0)=C(0)+1
END SUB
DIM TT(0 TO 13*4+1)
SUB add(C1(),C2(), C()) !C1を上、C2を下にパケットを重ねる
FOR i=1 TO C1(0)
LET TT(i)=C1(i)
NEXT i
FOR i=1 TO C2(0) !続けて
LET TT(C1(0)+i)=C2(i)
NEXT i
LET C(0)=C1(0)+C2(0)
FOR i=1 TO C(0)
LET C(i)=TT(i)
NEXT i
END SUB
SUB clr(C()) !パケットをクリアする
LET C(0)=0
END SUB
SUB rev(C()) !パケットを裏返す
FOR i=1 TO INT(C(0)/2)
swap C(i),C(C(0)-i+1)
NEXT i
END SUB
SUB disp(C(),m$) !パケットを上から順に表示する
PRINT m$;"(";C(0);"枚)";
FOR i=1 TO C(0)
PRINT C(i);
NEXT i
PRINT
END SUB
!-------------------- ここまでがサブルーチン
LET N=12 !枚数
DIM S(0 TO N),H(0 TO N) !スペード、ハートパケットの初期化
FOR i=1 TO N !整列
LET S(i)=i !スペード 1〜13
LET H(i)=i+13*2 !ハート 27〜39
NEXT i
LET H(0)=N !枚数
LET S(0)=N
!テーブルの初期化
DIM Y1(0 TO N),Y2(0 TO N),Y3(0 TO N) !山1、山2、捨て場
CALL clr(Y1) !山のクリア
CALL clr(Y2)
CALL clr(Y3)
CALL dump !内容を確認する
SUB dump
CALL disp(S,"スペード") !トレース
CALL disp(H,"ハート")
CALL disp(Y1,"山1")
CALL disp(Y2,"山2")
CALL disp(Y3,"捨て場")
PRINT
END SUB
!1回目
INPUT PROMPT "好きな数字(2〜N)?": K !好きな数字 1〜N
CALL routine
SUB routine !作業の定義
FOR x=1 TO N !手持ちのカードがなくなるまで
PRINT x;"枚目をテーブルへ"
CALL dec(S,1,w) !削除する
IF x=K THEN !一致する枚数目なら捨て場へ
!IF MOD(x,K)=0 THEN !一致する枚数目なら捨て場へ
CALL inc(Y3,1,w)
CALL dec(H,1,w) !代替として場から
END IF
IF MOD(x,2)=0 THEN !左右交互で山に置く
CALL inc(Y2,1,w)
ELSE
CALL inc(Y1,1,w)
END IF
INPUT PROMPT "カードのマーク?": c$
INPUT PROMPT "数字(1〜N)?": K
IF UCASE$(c$)="H" THEN
LET w=H(K) !スペードの列になっている
LET w=S(w)
ELSE
LET w=MOD(S(K),13) !ハートの列になっている
LET w=H(w)
END IF
PRINT mid$(mk$,INT(w/13)+1,1); MOD(w,13)
PRINT "----- 最初の状態 -----"
CALL ready
CALL printa(s) ! スペード
CALL printa(h) ! ハート
PRINT
!
FOR R=1 TO 12
PRINT "----- Request";R;"の場合-----"
CALL ready
LET k=1
DO WHILE k< 13
FOR i=1 TO 12
LET j=MOD(i,2)*7+INT(i/2) ! 分けた2つを重ねた時の位置。
IF i=R THEN
LET t(j)=h(k) ! ハートをテーブルへ
LET w(k)=s(i) ! 手元(最初スペード)を「捨て」へ
LET k=k+1
ELSE
LET t(j)=s(i) ! 手元(最初スペード)をテーブルへ
END IF
NEXT i
MAT s=t ! テーブルを手元(最初スペード)へ
LOOP
CALL printa(s) ! 比較・・・手元(最初スペード)
CALL printa(w) ! 比較・・・「捨て」の重なり
PRINT
NEXT R
SUB printa(a())
FOR n=1 TO 12
PRINT USING "## ":a(n);
NEXT n
PRINT " …互いに Index."
END SUB
SUB ready
FOR i=1 TO 12
LET s(i)=i
LET h(i)=i
NEXT i
END SUB
!補助ルーチン
SUB PermPrintOut(A()) !表示する ※標準形(2行n列の行列表記する)
!PRINT "┌";
!FOR i=1 TO UBOUND(A)
! PRINT USING "###": i;
!NEXT i
!PRINT " ┐"
!PRINT "└";
FOR i=1 TO UBOUND(A)
PRINT USING "###": A(i);
NEXT i
!PRINT " ┘";
PRINT
END SUB
!置換
SUB PermIdentity(A()) !恒等置換
FOR i=1 TO UBOUND(A)
LET A(i)=i
NEXT i
END SUB
SUB PermMultiply(A(),B(), AB()) !積AB ※AB≠BA、A(BC)=(AB)C
LET ua=UBOUND(A)
LET ub=UBOUND(B)
IF ua=ub THEN
FOR i=1 TO ua
LET AB(i)=A(B(i)) !※合成写像(AB)(i)=A(B(i))
NEXT i
ELSE
PRINT "次元が違います。A=";ua;" B=";ub
STOP
END IF
END SUB
!-------------------- ここまでがサブルーチン
!main
LET N=12 !※2,4,10,12
!A=┌ 1 2 3 4 ┐=(1 2 4 3) ※1行目の順番は固定とする
! └ 2 4 1 3 ┘
DATA 2,4,6,8,10,12,1,3,5,7,9,11 !配列変数の「添え字と値」に対応させる
!DATA 2,4,6,8,10,1,3,5,7,9 !N=10
!DATA 2,4,1,3 !N=4
!DATA 2,1 !N=2
DIM A(N)
MAT READ A
FOR i=1 TO N
PRINT USING "###": i;
NEXT i
PRINT
DIM B(N)
CALL PermIdentity(B) !初期値
DIM c(N)
FOR k=1 TO N !回数
CALL PermMultiply(B,A,c) !シャッフル
PRINT "K=";k
CALL PermPrintOut(c) !何回か実行すると元に戻る
MAT B=c
NEXT k
!13以外の数Nに、自分自身Nを加えて新しい数を作る。
!その数が13より大きいときは、13を引く。
DIM A(13),B(13)
FOR k=1 TO 12
LET A(k)=k
LET B(k)=0
NEXT k
FOR i=1 TO 12
FOR k=1 TO 12
LET B(k)=MOD(B(k)+A(k),13)
NEXT k
LET B(13)=13
MAT PRINT B;
NEXT i
END
1000 !トランプのマジック
1010
1020 !パケット操作のシミュレーション
1030
1040 SUB dec(C(),p, w) !上からp位置のカードを削除する ※1≦p
1050 LET w=C(p)
1060 FOR i=p TO C(0)-1 !前に詰める
1070 LET C(i)=C(i+1)
1080 NEXT i
1090 LET C(0)=C(0)-1 !枚数
1100 END SUB
1110 SUB inc(C(),p,w) !上からp位置にカードを追加する
1120 IF p<=C(0) THEN
1130 FOR i=C(0) TO p STEP -1 !後ろにずらす
1140 LET C(i+1)=C(i)
1150 NEXT i
1160 ELSE
1170 LET p=C(0)+1 !最後へ
1180 END IF
1190 LET C(p)=w
1200 LET C(0)=C(0)+1 !枚数
1210 END SUB
1220 DIM TT(0 TO 13*4+1) !作業用 ※1デッキ分
1230 SUB add(C1(),C2(), C()) !C1を上、C2を下に重ねる
1240 FOR i=1 TO C1(0) !C1
1250 LET TT(i)=C1(i)
1260 NEXT i
1270 FOR i=1 TO C2(0) !続けてC2
1280 LET TT(C1(0)+i)=C2(i)
1290 NEXT i
1300 LET TT(0)=C1(0)+C2(0) !枚数
1310 CALL copy(TT,TT(0), C)
1320 END SUB
1330 SUB clr(C()) !空にする
1340 LET C(0)=0
1350 END SUB
1360 SUB rev(C()) !裏返す
1370 FOR i=1 TO INT(C(0)/2)
1380 swap C(i),C(C(0)-i+1) !上下を入れ替える
1390 NEXT i
1400 END SUB
1410 SUB del(C(),p,q) !p位置からq位置までのカードを削除する ※1≦p≦q
1420 IF p>C(0) THEN
1430 PRINT "無効です。";p;q
1440 ELSE
1450 IF p>q THEN
1460 PRINT "p>qで無効です。";p;q
1470 ELSE
1480 LET q=MIN(q,C(0))
1490 FOR i=q+1 TO C(0) !残りを繋げる
1500 LET C(p+i-q-1)=C(i)
1510 NEXT i
1520 LET C(0)=C(0)-(q-p+1) !枚数
1530 END IF
1540 END IF
1550 END SUB
1560 SUB shuffle(C()) !リフルシャッフルを行う ※後半、前半の順に重ねる
1570 FOR i=1 TO C(0)
1580 LET TT(i)=C(INT(i/2)+MOD(i,2)*(INT(C(0)/2)+1))
1590 !LET TT(i)=C(INT((i-1)/2)+MOD(i-1,2)*INT(C(0)/2)+1) !※前半、後半の順
1600 NEXT i
1610 LET TT(0)=C(0) !枚数
1620 CALL copy(TT,TT(0), C)
1630 END SUB
1640 SUB cut(C(),p) !カットする ※p位置以降が上になる
1650 LET p=MIN(p,C(0))
1660 FOR i=1 TO p-1 !前半部分を後へ
1670 LET TT(C(0)+i-p+1)=C(i)
1680 NEXT i
1690 FOR i=p TO C(0) !後半部分を前へ
1700 LET TT(i-p+1)=C(i)
1710 NEXT i
1720 LET TT(0)=C(0) !枚数
1730 CALL copy(TT,TT(0), C)
1740 END SUB
1750 SUB copy(C1(),p, C()) !上からp位置までをコピーする
1760 LET p=MIN(p,C1(0))
1770 FOR i=1 TO p !copy it
1780 LET C(i)=C1(i)
1790 NEXT i
1800 LET C(0)=p !枚数
1810 END SUB
1820 SUB move(C1(),p, C()) !上からp位置までを移動する
1830 CALL copy(C1,p,C)
1840 CALL del(C1,1,p)
1850 END SUB
1860 SUB disp(C(),m$) !上から順に表示する
1870 PRINT m$;"(";C(0);"枚)";
1880 FOR i=1 TO C(0)
1890 PRINT C(i);
1900 NEXT i
1910 PRINT
1920 END SUB
1930
1940
1950 DEF MarkOfCard$(w)=mid$(mk$,INT(w/13)+1,1) !カードを表示する
1960 DEF NumOfCard(w)=MOD(w,13)
1970 DEF CntOfPacket(C())=C(0) !パケット内のカードの枚数
1980
1990 LET mk$="SCHD" !マーク
2000 LET nm$=" A 1 2 3 4 5 6 7 8 910 J Q K" !※2文字ずつ
2010
2020 !スペード、クラブ、ハート、ダイヤパケットを初期化する
2030 DIM cS(0 TO 13),cC(0 TO 13),cH(0 TO 13),cD(0 TO 13)
2040 FOR i=1 TO 13 !整列
2050 LET cS(i)=i !スペード 1〜13
2060 LET cC(i)=i+13 !クラブ 14〜16
2070 LET cH(i)=i+13*2 !ハート 27〜39
2080 LET cD(i)=i+13*3 !ダイヤ 40〜52
2090 NEXT i
2100 LET cS(0)=13 !枚数
2110 LET cC(0)=13
2120 LET cH(0)=13
2130 LET cD(0)=13
2140 !-------------------- ここまでがサブルーチン
2150
2160
2170 LET N=12 !枚数
2180
2190 DIM Y1(0 TO N+1),Y2(0 TO N+1),Y3(0 TO N+1),Y4(0 TO N+1) !山1〜12
2200 DIM Y5(0 TO N+1),Y6(0 TO N+1),Y7(0 TO N+1),Y8(0 TO N+1)
2210 DIM Y9(0 TO N+1),Y0(0 TO N+1),Yj(0 TO N+1),Yq(0 TO N+1)
2220
2230 DIM S(0 TO N+1),H(0 TO N+1) !スペード、ハートパケットの初期化
2240 CALL copy(cS,N, S)
2250 CALL copy(cH,N, H)
2260
2270 CALL dump !内容を確認する
2280 SUB dump
2290 CALL disp(S,"スペード") !トレース
2300 CALL disp(H,"ハート")
2310 CALL disp(Y1,"山1")
2320 CALL disp(Y2,"山2")
2330 CALL disp(Y3,"捨て場")
2340 PRINT
2350 END SUB
2360
2370
2380 !1回目
2390 INPUT PROMPT "好きな数字(1〜N)?": K !好きな数字 1〜N
2400
2410 CALL routine
2420 SUB routine !作業の定義
2430 FOR x=1 TO N !手持ちのカードがなくなるまで
2440 !!!PRINT x;"枚目をテーブルへ"
2450 CALL dec(S,1,w) !削除する
2460 IF x=K THEN !一致する枚数目なら捨て場へ
2470 CALL inc(Y3,1,w)
2480 CALL dec(H,1,w) !代替として場から
2490 END IF
2500
2510 IF MOD(x,2)=0 THEN !左右交互で山に置く
2520 CALL inc(Y2,1,w)
2530 ELSE
2540 CALL inc(Y1,1,w)
2550 END IF
2560
2570 !!!CALL dump !内容を確認する
2580 NEXT x
2590 !!!PRINT
2600 END SUB
2610
2620
2630 !2回〜N回まで
2640 DO
2650 CALL add(Y1,Y2, S) !山を重ねて手に持つ
2660 CALL rev(S)
2670
2680 CALL clr(Y1) !山のクリア
2690 CALL clr(Y2)
2700
2710 IF CntOfPacket(H)=0 THEN EXIT DO !テーブル上のハートパケットがなくなるまで
2720
2730 CALL routine
2740 LOOP
2750
2760
2770 CALL move(Y3,99, H) !最終の状態
2780 CALL rev(H)
2790
2800 PRINT
2810 CALL dump !内容を確認する
2820
2830
2840 CALL surprise
2850 SUB surprise
2860 INPUT PROMPT "カードのマーク(S,H)?": c$
2870 INPUT PROMPT "数字(1〜N)?": K
2880
2890 IF UCASE$(c$)="H" THEN
2900 LET w=H(K) !スペードの列になっている
2910 LET w=S(w)
2920 ELSE
2930 LET w=MOD(S(K),13) !ハートの列になっている
2940 LET w=H(w)
2950 END IF
2960 PRINT MarkOfCard$(w); NumOfCard(w) !カードを表示する
2970 END SUB
2980
2990 !---------- ↑↑↑↑↑ ---------- 前半のマジック
3000
3010
”
INPUT PROMPT "好きな数字(2〜N:N<=12)": K
2450
2460 CALL routine2_1(H) !各山へ分配する
2470 SUB routine2_1(C())
2480 FOR x=1 TO N+1
2490 CALL dec(C,1,w) !1枚ずつ
2500 SELECT CASE MOD(x-1,K)+1 !それぞれの山へ
”
好きな山を選択するときは、1なら動きはないからDATA の最初は0?
あと2920行では wlk(K)→wlk(x)?
2870 INPUT PROMPT "好きな山を選ぶ(1〜K:K<=N,ただし0は終了)": x
2880
2890 DIM wlk(N)
2900 DATA 1,1,1,1,-2,1,-1,-3,4,3,2,1 !回収方法 ※1なら右へ1、−2なら左へ2の意
2910 MAT READ wlk
2920 LET KEY1=wlk(K) !終端位置を記憶する
2930
2940 DIM yy(0 TO N+1)
2950 CALL routine2_2 !各山から回収する
!OPTION ARITHMETIC decimal_high
LET t0=TIME
DIM S(1000000) !S1,S2,…,Sn
LET S(1)=1
FOR k=2 TO 1000000
LET S(k)=S(k-1)+k !左辺 1+ … +(k-1)+k の値
NEXT k
LET c=0 !個数
FOR n=1 TO 1000000
LET key=S(n)/2 !「全体の半分の値」を見つける
LET L=1 !下限
LET H=n !上限
DO WHILE L<=H !逆転したら終了
LET M=INT((L+H)/2) !中央
IF S(M)<=key THEN LET L=M+1 !絞り込む
IF S(M)>=key THEN LET H=M-1
LOOP
!!!PRINT n;L;H
IF L=H+2 THEN !見つかったら
LET c=c+1
PRINT c;"個目"
PRINT "1 + … +";M;"=";M+1; !左辺と=
IF M<n-1 THEN !整形のため
PRINT "+ … +";n; !右辺
END IF
PRINT "(=";S(M);")" !和
END IF
NEXT n
PRINT "計算時間=";TIME-t0
END
●「2次方程式を解く」の別解としてのサンプル
FOR k=1 TO 1000000
nについての2次方程式 n^2+n-2*(k^2+k)=0 を解いて正の整数解を得る
NEXT k
これは、数列{Sk,Sk+1,…}の中から、2*Skを探すことです。
無限個の中を探索できないので、(実際は小さい順に整列しているので途中で中止する)
!OPTION ARITHMETIC decimal_high
LET t0=TIME
LET c=0 !個数
FOR N=2 TO 1000000
LET S=N*(N+1)/2 !全部の和
LET a=INT(SQR(S)) !=が入る箇所の可能性
FOR k=a TO a+1
LET L=k*(k+1)/2 !左辺の和
IF 2*L=S THEN !2*左辺=全部の和なら、条件をみたす
LET c=c+1
PRINT c;"個目"
PRINT "1 + … +";k;"="; !左辺と=
IF i=N-1 THEN !整形のため
PRINT k+1;"(=";L;")" !右辺と和
ELSE
PRINT k+1;"+ … +";N;"(=";L;")"
END IF
END IF
NEXT k
NEXT N
PRINT "計算時間=";TIME-t0
END
!OPTION ARITHMETIC decimal_high
LET t0=TIME
LET a=1000000
LET n=1 !先頭から
LET k=1
LET c=0 !個数
DO UNTIL n>a OR k>a-1 !どちらかのデータ列が終わるまで
LET s1=n*(n+1)/2 !データ列を得る
LET s2=2*k*(k+1)/2
IF s1=s2 THEN !マージする
LET c=c+1
PRINT c;"個目"
PRINT "1 + … +";k;"=";k+1; !左辺と=
IF k<n-1 THEN !整形のため
PRINT "+ … +";n; !右辺
END IF
PRINT "(=";s1/2;")" !和
LET k=k+1
LET n=n+1
ELSEIF s1>s2 THEN
LET k=k+1
ELSE
LET n=n+1
END IF
LOOP
PRINT "計算時間=";TIME-t0
END
LET k=4 ! 4行
LET n=k*(k+1)/2 ! n=10
DIM a(k,k),check(n)
FOR maxn=1 TO CEIL(k/2)
FOR r=1 TO n^(n/2)
MAT check=ZER
LET a(1,maxn)=n
LET check(n)=1
FOR i=1 TO k
FOR j=1 TO k+1-i
IF NOT (i=1 AND j=maxn) THEN
DO
LET
num=INT((n-1)*RND)+1
LOOP UNTIL check(num)=0
LET a(i,j)=num
LET check(num)=1
END IF
NEXT j
NEXT i
!MAT PRINT a
CALL diff
IF p=0 THEN MAT PRINT a
LET p=0
NEXT r
NEXT maxn
SUB diff
FOR i=1 TO k-1
FOR j=1 TO k-i
IF ABS(a(i,j)-a(i,j+1))<>a(i+1,j) THEN
LET p=1
EXIT SUB
END IF
NEXT j
NEXT i
END SUB
END
PUBLIC NUMERIC ANSWER_COUNT !解答数
LET ANSWER_COUNT=0
LET K=5 !段数 ※1〜
LET N=K*(K+1)/2 !1〜Kまでの数字
DIM A(N)
MAT A=ZER
LET t0=TIME
PRINT K;"段"
PRINT "1 〜";N;"までの数字"
CALL backtrack(1,K,N,A)
IF ANSWER_COUNT=0 THEN PRINT "解なし"
PRINT "計算時間=";TIME-t0
END
EXTERNAL SUB backtrack(p,K,N,A())
FOR nm=1 TO N
LET A(p)=nm !仮に設定してみる
CALL checkrule(p,nm,N,A, rc) !条件を満たすなら
IF rc=1 THEN
IF p=N THEN !すべて埋まったら
LET ANSWER_COUNT=ANSWER_COUNT+1
PRINT ANSWER_COUNT;"個目"
FOR i=K TO 1 STEP -1 !上段から
PRINT REPEAT$(" ",K-i); !右へシフト
FOR j=1 TO i !この段の数字の数
PRINT USING "###": A((i-1)*i/2+j);
NEXT j
PRINT
NEXT i
!!!MAT PRINT A;
ELSE
CALL backtrack(p+1,K,N,A) !次へ
END IF
END IF
LET A(p)=0 !元に戻す
NEXT nm
END SUB
EXTERNAL SUB checkrule(p,nm,N,M() ,rc) !条件が満たすかどうか確認する
LET rc=0
!●数字は重複していないか?
FOR i=1 TO p-1
IF nm=M(i) THEN EXIT SUB !見つかったのでNG!
NEXT i
!●上段の2数の差?
!M(p)の添え字番号と配置
!11 12 … 5段目 s=11
! 7 8 9 10 4段目 s=7
! 4 5 6 3段目 s=4
! 2 3 2段目 s=2
! 1 1段目 s=1
!
!M(p-1) M(p) x段目
! M(p-x)
LET a=1/2 !段数を得る ※xの2次方程式(x-1)*x/2+1-p=0の解
LET b=-1/2
LET c=1-p
LET D=b^2-4*a*c !判別式 ※この解は実数のみ
LET x=INT((-b+SQR(D))/(2*a))
IF x>1 THEN !2段目以降なら
IF p>(x-1)*x/2+1 THEN !この段の2列目以降なら
IF ABS(M(p-1)-M(p))<>M(p-x) THEN EXIT SUB !不成立なのでNG!
END IF
END IF
!●左右対称
IF p=N AND M(p)<M(p-x+1) THEN EXIT SUB !上段の左端と右端
LET rc=1 !OK!
END SUB
PUBLIC NUMERIC ANSWER_COUNT !解答数
LET ANSWER_COUNT=0
LET K=5 !段数 ※1〜
LET N=K*(K+1)/2 !1〜Nまでの数字
DIM F(N),FF(N),B(K),BB(K)
MAT F=ZER
MAT B=ZER
LET t0=TIME
PRINT K;"段"
PRINT "1 〜";N;"までの数字"
CALL perm(1,N,K, F,B,FF,BB)
IF ANSWER_COUNT=0 THEN PRINT "解なし"
PRINT "計算時間=";TIME-t0
END
EXTERNAL SUB perm(p,N,R, F(),B(),FF(),BB()) !順列nPrを生成する
FOR nm=1 TO N !上段のK個の数を決める
IF F(nm)=0 THEN !数字は重複なしに埋める
LET F(nm)=1 !使用中とする
LET B(p)=nm !仮に設定してみる
IF p=R THEN !すべて埋まったら
CALL checkrule(R,F,B,FF,BB, rc) !条件を満たすなら
IF rc=1 THEN
LET ANSWER_COUNT=ANSWER_COUNT+1
PRINT ANSWER_COUNT;"個目"
MAT BB=B
FOR j=1 TO R !上段
PRINT USING "###": BB(j);
NEXT j
PRINT
FOR i=R-1 TO 1 STEP -1 !下段へ
PRINT REPEAT$(" ",R-i); !右へシフト
FOR j=1 TO i !この段の数字の数
LET BB(j)=ABS(BB(j)-BB(j+1))
PRINT USING "###": BB(j);
NEXT j
PRINT
NEXT i
END IF
ELSE
CALL perm(p+1,N,R, F,B,FF,BB) !次へ
END IF
LET B(p)=0 !元に戻す
LET F(nm)=0
END IF
NEXT nm
END SUB
EXTERNAL SUB checkrule(K,F(),B(),FF(),BB(), rc) !条件が満たすかどうか確認する
LET rc=0
!●左右対称
IF B(1)>B(K) THEN EXIT SUB !上段の左端と右端
!●上段の2数の差?
MAT BB=B !作業配列へ
MAT FF=F
FOR x=K-1 TO 1 STEP -1 !x段目
FOR j=1 TO x !1つ下の段
LET p=ABS(BB(j)-BB(j+1))
IF FF(p)=1 THEN EXIT SUB !数字が重複していないか
LET BB(j)=p
LET FF(p)=1 !使用中とする
NEXT j
NEXT x
LET rc=1 !OK!
END SUB
DECLARE EXTERNAL SUB combi
PUBLIC NUMERIC k,n,h,pt,count
LET t0=TIME
LET k=5 ! 行数
LET n=k*(k+1)/2 ! 最大値
LET h=INT(k/2) ! 半分
LET pt=MOD(k,2) ! 奇偶
DIM nn(n-1),c(k-1)
MAT nn=ZER
LET count=0
LET j=0
CALL combi(nn,1,k-1,j,c)
PRINT TIME-t0;"秒",count;"回"
END
EXTERNAL SUB differ(p()) !注意:一部改良しました
DIM a(k,k),ck(n-1)
LET a(1,1)=n
FOR j=2 TO k
LET a(1,j)=p(j-1)
NEXT j
CALL check
FOR j=2 TO h
SWAP a(1,j-1),a(1,j)
CALL check
NEXT j
IF pt=1 AND p(1)<p(k-1) THEN ! nが中央のとき
SWAP a(1,h),a(1,h+1)
CALL check
END IF
SUB check
LET count=count+1
MAT ck=ZER
FOR r=1 TO k-1
LET ck(p(r))=1
NEXT r
FOR ii=1 TO k-1
FOR jj=1 TO k-ii
LET d=ABS(a(ii,jj)-a(ii,jj+1))
IF ck(d)=1 THEN EXIT SUB ! 数値重複
LET ck(d)=1
LET a(ii+1,jj)=d
NEXT jj
NEXT ii
MAT PRINT a; ! 解あり
END SUB
END SUB
REM 十進BASIC添付"\BASICw32\SAMPLE\COMBINAT.BAS"より
REM 1〜n-1の集合からr個を選ぶ組合せを生成する。
EXTERNAL SUB combi(nn(),kk,r,j,c())
DECLARE EXTERNAL SUB permu
! kk以降の数からr個を選択する
IF r=0 THEN
FOR i=1 TO n-1
IF nn(i)=1 THEN
LET j=j+1
LET c(j)=i
END IF
NEXT i
!MAT PRINT c;
CALL permu(c,1)
LET j=0
ELSE
FOR i=kk TO n-r
LET nn(i)=1
CALL combi(nn,i+1,r-1,j,c)
LET nn(i)=0
NEXT i
END IF
END SUB
REM 十進BASIC添付"\BASICw32\SAMPLE\PERMUTAT.BAS"より
REM (k-1)個の数値の順列を辞書式順序で生成する。
EXTERNAL SUB permu(p(),r)
DECLARE EXTERNAL SUB differ
IF r=k-1 THEN
!MAT PRINT p;
CALL differ(p)
ELSE
FOR i=r TO k-1
LET t=p(i)
FOR j=i-1 TO r STEP -1
LET p(j+1)=p(j)
NEXT j
LET p(r)=t
CALL permu(p,r+1)
LET t=p(r)
FOR j=r TO i-1
LET p(j)=p(j+1)
NEXT j
LET p(i)=t
NEXT i
END IF
END SUB
OPTION CHARACTER byte
SET TEXT BACKGROUND "opaque"
SET TEXT font"",14
OPTION BASE 0
DIM wb(8,8)
!
LET lb$=REPEAT$( CHR$(0),10000*8*8) ! N=1〜7: 1,1,1,4,56,9408,16942080
LET N= 6 ! 2,3,4,5,6
LET cp= 1000 ! カウンターの表示間隔(1~20000)、小さいと速度低下。大きいと中止が困難。
!
CALL main
SUB makelb(x,y)
local element
FOR element=0 TO N-1
FOR i=0 TO x-1
IF element=wb(y,i) THEN EXIT FOR ! break;
NEXT i
IF i>x-1 THEN
FOR i=0 TO y-1
IF element=wb(i,x) THEN EXIT FOR ! break;
NEXT i
IF i>y-1 THEN
LET wb(y,x)=element
IF y=N-1 AND x=N-1 THEN
!----memcpy(lb[lbs++], wb, sizeof(wb));
LET w=1+64*lbs
FOR i=0 TO N-1
FOR j=0 TO N-1
LET lb$(w+j:w+j)=CHR$(wb(i,j))
NEXT j
LET w=w+8
NEXT i
!--------モニター
IF MOD(lbs,1000)=0 THEN PRINT "作成中。N=";N;"lbs=";lbs
!--------
LET lbs=lbs+1
EXIT SUB ! return;
END IF
IF
y=N-1 THEN CALL makelb(x+1,1) ELSE CALL makelb((x),y+1)
END IF
END IF
NEXT element
END SUB
SUB main
FOR i=0 TO N-1
LET wb(i,0)=i ! =element
LET wb(0,i)=i ! =element
NEXT i
!------
PRINT "標準のラテン方陣の作成。"
LET lbs=0
CALL makelb(1,1)
PRINT "作成終了。"
PRINT
PRINT "次数 N=";N;"lbs=";lbs;"個"
PRINT "標準のラテン方陣 2つで、"
PRINT " オイラー方陣を構成可?"
LET w$=STR$(lbs)
IF lbs>2 THEN LET w$=w$& "+"& STR$(lbs-1)
IF lbs>3 THEN LET w$=w$& "+"& STR$(lbs-2)
IF lbs>4 THEN LET w$=w$& "+..."
IF lbs>1 THEN LET w$=w$& "+1"
PLOT TEXT,AT 0.1,0.9 :w$& " が検査回数です。"
PLOT TEXT,AT 0.1,0.8 :"("& STR$(lbs) &"+1)*"&
STR$(lbs)& "/2= "& STR$((lbs+1)*lbs/2)& "回まで、何時間?"
PRINT "機械語実行中"
IF check1( CallBackAdr(9), N+16*cp, lbs, lb$)=0 THEN PRINT "解は、有りませんでした。"
PRINT "終了しました。"
END SUB
!-------------------------------------
FUNCTION check1( moniのアドレス, Ncp, lbs, lb$ )
ASSIGN "hojin_43.dll","start00"
END FUNCTION
!-------------------------------------
! hojin.dll が使用する文で、状態表示用。
SUB moni(message$,count), callback 9
PRINT message$;
PLOT TEXT,AT 0.1, 0.7 :"count= "&STR$(count)
END SUB
!「さいころの回転」のシミュレーション
!置換(Permutation)の計算
SUB PermPrintOut(A()) !表示する
MAT PRINT USING(REPEAT$(" ##",UBOUND(A))): A;
PRINT
END SUB
SUB PermIdentity(A()) !恒等置換
FOR i=1 TO UBOUND(A)
LET A(i)=i
NEXT i
END SUB
SUB PermInverse(A(), iA()) !逆置換 ※iAはA以外の配列を指定すること
FOR i=1 TO UBOUND(A)
LET iA(A(i))=i
NEXT i
END SUB
SUB PermMultiply(A(),B(), AB()) !積AB ※ABはAかつB以外の配列を指定すること
LET ua=UBOUND(A)
LET ub=UBOUND(B)
IF ua=ub THEN
FOR i=1 TO ua
LET AB(i)=A(B(i)) !※合成写像(AB)(i)=A(B(i))
NEXT i
ELSE
PRINT "次元が違います。A=";ua;" B=";ub
STOP
END IF
END SUB
!-------------------- ここまでがサブルーチン
LET N=6
!展開図の配置と面番号(配列の添え字)との関係
! □ 後 1
!□□□□ 左上右下 2345
! □ 正 6
!---------- ↓↓↓↓↓ ----------
DIM A(N)
DATA 5,4,1,3,6,2 !目の配置 ※展開図参照
MAT READ A
!LET s$="DRDRDR" !手順 1
!LET s$="RRRDDD" !手順 2
!LET s$="RRDDDR" !手順 3
!LET s$="RRDRDD" !手順 4
!LET s$="RDDDRR" !手順 5
LET s$="RDLDRRRD" !手順 6
!---------- ↑↑↑↑↑ ----------
DIM U(N),D(N),L(N),R(N) !置換
! 1,2,3,4,5,6
DATA 3,2,6,4,1,5 !上 ※正面を上面にするの(図での水平軸)回転
!!!DATA 5,2,1,4,6,3 !下
DATA 1,3,4,5,2,6 !左
!!!DATA 1,5,2,3,4,6 !右
MAT READ U
CALL PermInverse(U,D)
!!!MAT READ D
MAT READ L
CALL PermInverse(L,R)
!!!MAT READ R
SET WINDOW -1,5,5,-1 !表示領域
DRAW grid !格子
DIM T(N),TT(N) !作業配列
LET x=0.5 !左上
LET y=0.5
MAT T=A !初期状態を表示する
CALL disp(T)
FOR k=1 TO LEN(s$) !スクリプトを実行する
PLOT LINES: x,y; !経路の結線 始点
SELECT CASE UCASE$(s$(k:k)) !各方向へ
CASE "U","N"
CALL PermMultiply(T,U,TT)
LET y=y-1
CASE "D","S"
CALL PermMultiply(T,D,TT)
LET y=y+1
CASE "L","W"
CALL PermMultiply(T,L,TT)
LET x=x-1
CASE "R","E"
CALL PermMultiply(T,R,TT)
LET x=x+1
CASE ELSE
END SELECT
MAT T=TT !次へ
PLOT LINES: x,y; !終点
CALL disp(T)
NEXT k
SUB disp(T()) !現在の状態を表示する
CALL PermPrintOut(T)
LET nm=T(3) !グラフィックスによる
IF nm=1 THEN !中央
DRAW eye(4) WITH SHIFT(x,y)
END IF
IF nm=3 OR nm=5 THEN
DRAW eye(1) WITH SHIFT(x,y)
END IF
IF nm=2 OR nm=4 OR nm=5 OR nm=6 THEN !左斜め
DRAW eye(1) WITH SHIFT(x+0.25,y+0.25)
DRAW eye(1) WITH SHIFT(x-0.25,y-0.25)
END IF
IF nm=3 OR nm=4 OR nm=5 OR nm=6 THEN !右斜め
DRAW eye(1) WITH SHIFT(x+0.25,y-0.25)
DRAW eye(1) WITH SHIFT(x-0.25,y+0.25)
END IF
IF nm=6 THEN !中段
DRAW eye(1) WITH SHIFT(x+0.25,y)
DRAW eye(1) WITH SHIFT(x-0.25,y)
END IF
!!!SET TEXT JUSTIFY "center","half"
!!!PLOT TEXT ,AT x,y: STR$(T(3))
END SUB
PICTURE eye(c) !目の1つを表示する
SET AREA COLOR c
DRAW disk WITH SCALE(0.1)
END PICTURE
END
!2端子対回路(4端子回路)
! i1→┌──┐i2→
! a ─┤A B├─ b
!E1↑ │ │ ↑E2
! a'─┤C D├─ b'
! └──┘
!基本行列Fを用いて
! (E1)=(A B)(E2)
! (i1) (C D)(i2)
OPTION ARITHMETIC COMPLEX !複素数を扱う
LET j=SQR(-1) !虚数単位 ※電気系はjを使う
!●交流回路
LET f=60 !周波数[Hz]
LET w=2*PI*f !角周波数ω
DEF H2Ohm(L)=j*w*L ![H]を[Ω]へ
DEF F2Ohm(C)=1/(j*w*C) ![F]を[Ω]へ
DEF xL(L)=w*L !誘導リアクタンス
DEF xC(C)=1/(w*C) !容量リアクタンス
SUB DispS(z) !複素数をS表示する ※スタインメッツ(Steinmetz)
PRINT ABS(z);
IF ABS(z)<>0 THEN
IF arg(z)<>0 THEN PRINT "∠";DEG(arg(z));"°";
END IF
PRINT
END SUB
FUNCTION S2COMPLEX(l,th) !S表示(極座標形式)を複素数へ
LET S2COMPLEX=COMPLEX(l*COS(RAD(th)),l*SIN(RAD(th)))
END FUNCTION
!●2端子インピーダンス回路行列
! ─Z─ の場合 F=(1 Z)
! ─-─ (0 1)
SUB seriesF(Z,F(,))
LET F(1,1)=1
LET F(1,2)=Z
LET F(2,1)=0
LET F(2,2)=1
END SUB
! ─┬─ の場合 F=(1 0)
! Z (1/Z 1)
! ─┴─
SUB shuntF(Z,F(,))
WHEN EXCEPTION IN
LET F(1,1)=1
LET F(1,2)=0
LET F(2,1)=1/Z
LET F(2,2)=1
USE
PRINT "0で割れません。"
STOP
END WHEN
END SUB
!●パラメータの相互変換 ※一部
SUB F2Z(F(,), Z(,)) !FパラメータをZパラメータへ
LET Z(1,1)=F(1,1) !A
LET Z(1,2)=DET(F) !AD-BC
LET Z(2,1)=1
LET Z(2,2)=F(2,2) !D
WHEN EXCEPTION IN
MAT Z=(1/F(2,1))*Z !(1/C)倍
USE
PRINT "Zパラメータは存在しません。"
STOP
END WHEN
END SUB
SUB F2Y(F(,),Y(,)) !FパラメータをYパラメータへ
LET Y(1,1)=F(2,2) !D
LET Y(1,2)=-DET(F) !BC-AD
LET Y(2,1)=-1
LET Y(2,2)=F(1,1) !A
WHEN EXCEPTION IN
MAT Y=(1/F(1,2))*Y !(1/B)倍
USE
PRINT "Yパラメータは存在しません。"
STOP
END WHEN
END SUB
SUB Z2Y(Z(,),Y(,)) !ZパラメータをYパラメータへ
WHEN EXCEPTION IN
MAT Y=INV(Z) !Y=Z^-1
USE
PRINT "Yパラメータは存在しません。"
STOP
END WHEN
END SUB
!-------------------- ここまでがサブルーチン
DIM mF(2,2),mZ(2,2),mY(2,2) !F,Z,Yパラメータ
DIM T1(2,2),T2(2,2) !作業用
!●はしご回路の合成抵抗 a-b端子間
!a─R1┬R3┬R5┬ … ┬Rn┬─┬ …
! R2 R4 R6 Rn-1 Rn+1
!b──┴─┴─┴ ┴─┴─┴
!
LET R1=1 !1,2,1,2,…,1,2,1
LET R2=2
CALL seriesF(R1,T1) !─R1┬
CALL shuntF(R2,T2) ! R2
MAT mF=IDN !単位行列
FOR i=1 TO 5 !段数
MAT mF=mF*T1 !─R1┬R1┬ … ┬R1┬
MAT mF=mF*T2 ! R2 R2 R2 R2
NEXT i
MAT mF=mF*T1 !─R1┐
CALL F2Z(mF,mZ) !要素a
MAT PRINT mZ;
!●T型LC回路
! ─L─┬─L─
! C
! ─-─┴─-─
!ω=1[rad/sec]、L=2[H]、C=1[F]
LET L=2
LET C=1
LET w=1 !問題に合わせる
!●Fパラメータ、基本行列
MAT mF=IDN !単位行列
CALL seriesF(H2Ohm(L),T1)
MAT mF=mF*T1
CALL shuntF(F2Ohm(C),T2)
MAT mF=mF*T2
MAT mF=mF*T1
PRINT "Fパラメータ"
MAT PRINT mF;
!●Zパラメータ、インピーダンス行列 V=Z*I
CALL F2Z(mF,mZ)
PRINT "Zパラメータ"
MAT PRINT mZ;
!●Yパラメータ、アドミタンス行列 I=Y*V
CALL F2Y(mF,mY)
PRINT "Yパラメータ"
MAT PRINT mY;
!●Yパラメータ(別解)Y=Z^-1
CALL Z2Y(mZ,mY)
PRINT "Yパラメータ"
MAT PRINT mY;
END
前回 NO95 NOの御回答有難うございました。山中さんを中山さんと間違えて投稿しました。失礼を御許しください。
その後だいぶ10進BASICを進めてますが、下記の不具合でストップしてます。
MAT T=INV(A) が出来ないのです。
OPTION ARITHMETIC COMPLEX
LET j=SQR(-1)
LET R1=5000
LET R2=5000
LET C1=0.1*10^( -6 )
LET C2=0.1*10^( -6 )
LET F=100
LET SZ=0.001
LET NP=4
LET ZC1=1/(2*PI*F*C1)
LET ZC2=1/(2*PI*F*C2)
OPTION BASE 1
PRINT "ZCI=";ZC1
DIM A(NP,NP),B(NP,NP),T(NP,NP),E1(NP)
LET A(1,2)=1/R1+SZ*j
LET A(2,3)=1/R2+SZ*j
LET A(2,4)=SZ+1/ZC1*j
LET A(3,4)=SZ+1/ZC2*j
MAT PRINT A
LET E1(1)=1
LET E1(4)=0
PRINT"下記のごとくMAT PRINT E1とやると横に一文字になる。"
MAT PRINT E1
PRINT"下記のごとくMAT PRINT USING REPEAT$RIで縦に一文字並び良
好。"
MAT PRINT USING REPEAT$(" #.#### ",1):E1
MAT T=INV(A)
STOP
早速ですが、上記の文を作り、マトリクス[A]を作り実行すると、最後の MAT T=INV(A)で
「EXTYPE 3009 引数が定義外の値」となり、ストップします。
どこが不良の原因でしょうか。
また、一列のE(5)などを作り、PRINT E をやると、横一列に表示します。
四端子網の A*E 等は大丈夫でしょうか。縦に変更してT=TRAN(E) そしてA*T でしょうか。
> 早速ですが、上記の文を作り、マトリクス[A]を作り実行すると、最後の MAT T=INV(A)で
> 「EXTYPE 3009 引数が定義外の値」となり、ストップします。
> どこが不良の原因でしょうか。
行列Aが、逆行列を持たない行列だからです。
Aは筆算で逆行列は存在しますか?
> また、一列のE(5)などを作り、PRINT E をやると、横一列に表示します。
> 四端子網の A*E 等は大丈夫でしょうか。縦に変更してT=TRAN(E) そしてA*T でしょうか。
DIM A(3,3)
DIM X(3),B(3)
MAT B=A*X !(3行,3列)(3行,1列)=(3行,1列)として計算される
MAT PRINT B !横へ
MAT B=X*A !(1行,3列)(3行,3列)=(1行,3列)として計算される
MAT PRINT B !横へ
END
この場合、X,Bはベクトル扱いになります。
X,Bを行列として扱う場合は、(X,Bに対してTRNを適用する場合)
行または列のみの行列は、たとえば
3行1列なら DIM B(3,1)
1行3列なら DIM B(1,3)
としてください。
MAT READ px
DATA 0.20, 0.40, 0.60, 0.80, 0.70, 0.60, 0.50, 0.40, 0.30, 0.20, 0.40, 0.60
MAT READ py
DATA 0.11, 0.11, 0.11, 0.11, 0.29, 0.47, 0.65, 0.47, 0.29, 0.11, 0.11, 0.11
SET WINDOW -1/4,1/4, -1/4,1/4
!----------
LET N=3
DO
LET s=MOD(s,36)+1
LET s2=INT((s-1)/4)+1
SET DRAW mode hidden
CLEAR
DRAW D4(N) WITH SHIFT(-0.5,-0.5/SQR(3))*ROTATE(PI*2/36*s+PI)
SET DRAW mode explicit
WAIT DELAY 0.2
LOOP
!------
PICTURE D4(k)
IF 0< k THEN
DRAW D4(k-1) WITH SCALE(1/2,1/2)*SHIFT(1/4,SQR(3)/4) ! 上
DRAW D4(k-1) WITH SCALE(1/2,-1/2)*SHIFT(1/4,SQR(3)/4) ! 中
DRAW D4(k-1) WITH SCALE(1/2,1/2)*ROTATE(-PI*2/3)*SHIFT(1/4,SQR(3)/4) ! 左
DRAW D4(k-1) WITH SCALE(1/2,1/2)*ROTATE(PI*2/3)*SHIFT(1,0) ! 右
ELSE
DRAW Set01
END IF
END PICTURE
!------ 種の三角図
PICTURE Set01
PLOT LINES: 0,0; 1,0 ;0.5,SQR(3)/2 ;0,0
SET AREA COLOR 5 !2
DRAW disk WITH SCALE(0.1)*SHIFT(px(s2),py(s2)) ! 飾り1
SET AREA COLOR 6 !3
DRAW disk WITH SCALE(0.1)*SHIFT(px(s2+1),py(s2+1)) ! 飾り2
SET AREA COLOR 7 !4
DRAW disk WITH SCALE(0.1)*SHIFT(px(s2+2),py(s2+2)) ! 飾り3
SET AREA COLOR 1
DRAW disk WITH SCALE(0.1)*SHIFT(px(s2+3),py(s2+3)) ! 飾り4
END PICTURE
!4山でのシャッフル調査
100 OPTION BASE 1
110 INPUT PROMPT "カードの枚数は?":n
120 INPUT PROMPT "山の数は?:4を入力しておいて下さい。":p
130 INPUT PROMPT "シャッフル回数?":t
140
150 DIM a(n)
160 DIM b(n)
170 DIM c(n)
180 DIM d(n)
190 DIM e(n)
200 DIM f(n)
210
220 FOR i=1 TO n
230 LET a(i)=i
240 NEXT i
250
260 FOR q=1 TO t
270 FOR k=1 TO INT(n/p)
280 LET b(k)=a(p*(k-1)+1)
290 LET c(k)=a(p*(k-1)+2)
300 LET d(k)=a(p*(k-1)+3)
310 LET e(k)=a(p*(k-1)+4)
320 PRINT USING "####":b(k);
330 PRINT USING "####":c(k);
340 PRINT USING "####":d(k);
350 PRINT USING "####":e(k);
360 PRINT
370 NEXT k
380
390 FOR i=1 TO n/p
400 LET f(i)=b(n/p-i+1)
410 LET f(n/p+i)=c(n/p-i+1)
420 LET f(2*n/p+i)=d(n/p-i+1)
430 LET f(3*n/p+i)=e(n/p-i+1)
440 NEXT i
450
460 FOR i=1 TO n
470 LET a(i)=f(i)
480 PRINT ;q;"回";
490 PRINT USING "####":a(i);
500 PRINT
510 NEXT i
520
530 NEXT q
540 END
550
!3山でのシャッフル調査
100 OPTION BASE 1
110 INPUT PROMPT "カードの枚数は?":n
120 INPUT PROMPT "山の数は?:3を入力しておいて下さい。":p
130 INPUT PROMPT "シャッフル回数?":t
140
150 DIM a(n)
160 DIM b(n)
170 DIM c(n)
180 DIM d(n)
190!DIM e(n)
200 DIM f(n)
210
220 FOR i=1 TO n
230 LET a(i)=i
240 NEXT i
250
260 FOR q=1 TO t
270 FOR k=1 TO INT(n/p)
280 LET b(k)=a(p*(k-1)+1)
290 LET c(k)=a(p*(k-1)+2)
300 LET d(k)=a(p*(k-1)+3)
310 ! LET e(k)=a(p*(k-1)+4)
320 PRINT USING "####":b(k);
330 PRINT USING "####":c(k);
340 PRINT USING "####":d(k);
350 ! PRINT USING "####":e(k);
360 PRINT
370 NEXT k
380
390 FOR i=1 TO n/p
400 LET f(i)=b(n/p-i+1)
410 LET f(n/p+i)=c(n/p-i+1)
420 LET f(2*n/p+i)=d(n/p-i+1)
430 ! LET f(3*n/p+i)=e(n/p-i+1)
440 NEXT i
450
460 FOR i=1 TO n
470 LET a(i)=f(i)
480 PRINT ;q;"回";
490 PRINT USING "####":a(i);
500 PRINT
510 NEXT i
520
530 NEXT q
540 END
550
SET TEXT FONT "MS 明朝",12
SET TEXT BACKGROUND "OPAQUE"
SET POINT STYLE 1
!----------------
LET t$="アンモナイト"
LET N=101
LET xm=-0.63
LET ym=0.5
LET h=1.5
RANDOMIZE 19650218
SET WINDOW xm-h,xm+h, ym-h,ym+h
PLOT TEXT,AT xm+h*0.1,ym+h*0.85:t$& " N="& USING$("###",N)
SET POINT COLOR 44
CALL fa(N, 0.4, 0.2)
beep
!----------------
LET t$="シダの葉"
LET N=19
LET xm=0.32
LET ym=0.5
LET h=0.6
RANDOMIZE 19650218
SET WINDOW xm-h,xm+h, ym-h,ym+h
DRAW axes
PLOT TEXT,AT xm+h*0.1,ym+h*0.7:t$& " N="& USING$("###",N)
PLOT TEXT,AT xm-h*0.75, ym+h*0.85:"しばらく御待ち下さい。"
SET POINT COLOR 10
CALL fs(N, 0,0)
CALL fs(N, 0,0)
beep
PLOT TEXT,AT xm-h*0.75, ym+h*0.85:" 描画の終了 "
!------------------------------------------------------------
! 複数の縮小アファイン変換 (アンモナイト)
DEF A1x(x,y)=-0.289993*x-0.001347*y+0.593333
DEF A1y(x,y)= 0.001986*x-0.196662*y-0.32 ! p1=0.06124
DEF A2x(x,y)=-0.073058*x-0.024834*y+0.793333
DEF A2y(x,y)=-0.006353*x+0.285589*y-0.056667 ! p2=0.022236
DEF A3x(x,y)= 0.939186*x-0.218787*y-0.046667
DEF A3y(x,y)= 0.214337*x+0.958685*y+0.01 ! p3=0.916524
!------------------------------------------------------------
SUB fa(k, x,y)
IF 0< k THEN
CALL fa(k-1, A3x(x,y),A3y(x,y))
IF RND< 0.0668176 THEN CALL fa(k-1, A1x(x,y),A1y(x,y))
IF RND< 0.024261 THEN CALL fa(k-1, A2x(x,y),A2y(x,y))
END IF
PLOT POINTS: x,y
END SUB
!------------------------------------------------------------
! 複数の縮小アファイン変換 (シダの葉)
DEF W1x(x,y)= 0.836*x+0.044*y
DEF W1y(x,y)=-0.044*x+0.836*y+0.169 ! p1=0.4
DEF W2x(x,y)=-0.141*x+0.302*y
DEF W2y(x,y)= 0.302*x+0.141*y+0.127 ! p2=0.2
DEF W3x(x,y)= 0.141*x-0.302*y
DEF W3y(x,y)= 0.302*x+0.141*y+0.169 ! p3=0.2
DEF W4x(x,y)= 0
DEF W4y(x,y)= 0.175337*y ! p4=0.2
!------------------------------------------------------------
!確率的プロット(p1~p4)は、変形されています。
SUB fs(k, x,y)
IF 0< k THEN
CALL fs(k-1, W1x(x,y),W1y(x,y))
IF RND< 0.3 THEN CALL fs(k-1, W2x(x,y),W2y(x,y))
IF RND< 0.3 THEN CALL fs(k-1, W3x(x,y),W3y(x,y))
IF RND< 0.3 THEN CALL fs(k-1, W4x(x,y),W4y(x,y))
END IF
PLOT POINTS: x,y
END SUB
(2) 1090 LET f=60 !周波数
となってますが、周波数特性(ボード線図)などでは、
周波数 f=10 から 10000まで
等と成ります。
下に DATA 文を付け、READ DATA 等とやるのでしょうか。
周波数を DIM FF(fの指定,1)
出力も DIM EE2(出力の格納,1)
等とやると、可能とおもいますが、いかがでしょうか。
DIM mF(2,2),mZ(2,2) !F,Zパラメータ
DIM vi(2),vo(2) !電流や電圧のベクトル
DIM T1(2,2),T2(2,2) !作業用
!●1次RC回路、直列RC回路、ローパスフィルタ、積分回路
!i1→ i2→
! ─R─┬─
!E1↑ C ↑E2
! ─-─┴─
!E1=5[V]、R=1k[Ω]、C=0.1[μF]
LET R=1e3
LET C=0.1e-6
SUB routine
!※Fパラメータ、基本行列
MAT mF=IDN !単位行列
CALL seriesF(R,T1) !縦続接続
MAT mF=mF*T1
CALL shuntF(F2Ohm(C),T2)
MAT mF=mF*T2
!※Zパラメータ、インピーダンス行列 V=Z*I
CALL F2Z(mF,mZ)
!※(E1)=[F](E2)より
! (i1) (i2)
LET vi(1)=5 !5[V]
LET vi(2)=vi(1)/mZ(1,1) !i=V/R、?[A]
MAT T1=INV(mF) !出力側を算出する
MAT vo=T1*vi
END SUB
SET bitmap SIZE 800,400 !画面を横長へ
!※2SET bitmap SIZE 300,600 !画面を横長へ
SET WINDOW -1,6, -1,2 !表示領域
!※2SET WINDOW -1,6, -91,1 !表示領域
!※3SET WINDOW -1,6, -20,1 !表示領域
DRAW grid !目盛り
FOR f=1 TO 6 !x軸が対数
PLOT TEXT ,AT f-0.3,-0.15: mid$("10 100 1k 10k 100k1M ",4*(f-1)+1,4)
NEXT f
FOR f=10 TO 100000 STEP 100 !周波数[Hz]
CALL routine
LET vv=vo(1)/vi(1)
PLOT LINES: LOG10(f),ABS(vv); !振幅特性
!※2PLOT LINES: LOG10(f),DEG(ATN(Im(vv)/Re(vv))); !位相θ
!※3PLOT LINES: LOG10(f),20*LOG10(ABS(vv)); !利得[dB]
NEXT f
END
>(3) 例えば、このローパスフィルターが5段つずいたら、
行列のべき乗はMAT文では記述できませんので、FOR〜NEXT文で乗算を繰り返します。
例.
!●はしご回路の合成抵抗 a-b端子間
!a─R1┬R3┬R5┬ … ┬Rn┬ …
! R2 R4 R6 Rn-1 Rn+1
!b──┴─┴─┴ ┴─┴
!
LET R1=1 !1,2,1,2,…,1,2,1
LET R2=2
CALL seriesF(R1,T1) !─R1┬
CALL shuntF(R2,T2) ! R2
MAT mF=IDN !単位行列
FOR i=1 TO 5 !段数
MAT mF=mF*T1 !─R1┬R1┬ … ┬R1┬
MAT mF=mF*T2 ! R2 R2 R2 R2
NEXT i
MAT mF=mF*T1 !─R1┐
PRINT "Fパラメータ"
MAT PRINT mF;
!2重振子Chaos
LET g= 9.8 !m/s^2
LET m1=0.1 !kg
LET m2=0.1 !kg
LET L1= 5 !m
LET L2= 5 !m
!
LET dt=0.05 !sec. 演算ピッチ。
!
LET μ2=m2/(m1+m2)
LET L21=L2/L1
DEF ss1(w2,θ1,θ2)=-g/L1*SIN(θ1) -μ2*L21*w2^2*SIN(θ1-θ2)
DEF ss2(w1,θ1,θ2)=-g/L2*SIN(θ2) +w1^2*SIN(θ1-θ2)/L21
DEF D(θ1,θ2)=1-μ2*COS(θ1-θ2)^2
DEF α1(w1,w2,θ1,θ2)=( ss1(w2,θ1,θ2) -L21*μ2*COS(θ1-θ2)*ss2(w1,θ1,θ2) )/D(θ1,θ2)
DEF α2(w1,w2,θ1,θ2)=(-ss1(w2,θ1,θ2)*COS(θ1-θ2)/L21 +ss2(w1,θ1,θ2) )/D(θ1,θ2)
SUB RK(θ1,θ2,w1,w2)
LET w11=w1
LET w12=w2
LET α11=α1(w1,w2,θ1,θ2)
LET α12=α2(w1,w2,θ1,θ2)
!
LET w21=w1+α11*dt/2
LET w22=w2+α12*dt/2
LET α21=α1(w21,w22,θ1+w11*dt/2,θ2+w12*dt/2)
LET α22=α2(w21,w22,θ1+w11*dt/2,θ2+w12*dt/2)
!
LET w31=w1+α21*dt/2
LET w32=w2+α22*dt/2
LET α31=α1(w31,w32,θ1+w21*dt/2,θ2+w22*dt/2)
LET α32=α2(w31,w32,θ1+w21*dt/2,θ2+w22*dt/2)
!
LET w41=w1+α31*dt
LET w42=w2+α32*dt
LET α41=α1(w41,w42,θ1+w31*dt,θ2+w32*dt)
LET α42=α2(w41,w42,θ1+w31*dt,θ2+w32*dt)
!
LET θ1=θ1+(w11+2*w21+2*w31+w41)*dt/6
LET θ2=θ2+(w12+2*w22+2*w32+w42)*dt/6
LET w1=w1+(α11+2*α21+2*α31+α41)*dt/6
LET w2=w2+(α12+2*α22+2*α32+α42)*dt/6
END SUB
!----init.
LET a_1=PI*0.8 !初期角度1
LET a_2=PI*0.9 ! 〜 2
LET a_3=0 ! 初期角速度1
LET a_4=0 ! 〜 2
!
LET b_1=-a_1+0.001
LET b_2=-a_2
LET b_3=0
LET b_4=0
!
LET c_1=a_1
LET c_2=a_2+0.002
LET c_3=0
LET c_4=0
!
LET d_1=-a_1
LET d_2=-a_2+0.003
LET d_3=0
LET d_4=0
!
!----run
LET w=14
SET WINDOW -w,w,-w,w
SET LINE width 2 !4
SET LINE COLOR 2 !43
LET r1=SQR(m1)
LET r2=SQR(m2)
LET t0=TIME
DO
LET t=TIME
IF dt=< ABS(t-t0) THEN
SET DRAW mode hidden
CLEAR
PLOT TEXT,AT 0.25*w,0.9*w:"マウス 右ボタンで、終了。"
PLOT TEXT,AT -0.98*w,0.93*w,USING"演算ピッチ=#.### 秒":dt
PLOT TEXT,AT -0.98*w,0.87*w,USING"描画ピッチ=#.### 秒":t-t0
LET t0=t
SET AREA COLOR 15
DRAW disk WITH SCALE(3.86,4.67)
SET AREA COLOR 1
DRAW PDL1X2(a_1,a_2) WITH ROTATE(a_1)*SHIFT(-3,3)
DRAW PDL1X2(b_1,b_2) WITH ROTATE(b_1)*SHIFT(3,3)
DRAW PDL1X2(c_1,c_2) WITH ROTATE(c_1)*SHIFT(-3,-3)
DRAW PDL1X2(d_1,d_2) WITH ROTATE(d_1)*SHIFT(3,-3)
CALL RK(a_1,a_2,a_3,a_4)
CALL RK(b_1,b_2,b_3,b_4)
CALL RK(c_1,c_2,c_3,c_4)
CALL RK(d_1,d_2,d_3,d_4)
SET DRAW mode explicit
END IF
WAIT DELAY 0 !ノートパソコン等の消費電力を押える。
MOUSE POLL mx,my,mlb,mrb
LOOP UNTIL mrb=1
PICTURE PDL1X2(θ1,θ2)
DRAW circle WITH SCALE(0.3)
DRAW PDLM(L1,r1)
DRAW PDLM(L2,r2) WITH ROTATE(θ2-θ1)*SHIFT(0,-L1)
END PICTURE
PICTURE PDLM(L,r)
PLOT LINES: 0,0;0,-L
DRAW disk WITH SCALE(r)*SHIFT(0,-L)
END PICTURE
!SET bitmap SIZE 600,600 !画面を大きくする
SET WINDOW -0.5,6.5, -50,5 !表示領域
DRAW grid(1,5) !左端の目盛り
FOR f=1 TO 6 !x軸が対数
PLOT TEXT ,AT f-0.3,-0.15: mid$("10 100 1k 10k 100k1M ",4*(f-1)+1,4)
NEXT f
FOR f=10 TO 100000 STEP 100 !周波数[Hz]
CALL routine
LET vv=vo(1)/vi(1)
PLOT LINES: LOG10(f),20*LOG10(ABS(vv)); !利得[dB]
NEXT f
PLOT LINES
SET TEXT COLOR 2
FOR i=5 TO -45 STEP -5 !右端の縦軸目盛り
PLOT TEXT ,AT 6,i: STR$(i*2)&"°"
NEXT i
SET LINE COLOR 2
FOR f=10 TO 100000 STEP 100 !周波数[Hz]
CALL routine
LET vv=vo(1)/vi(1)
PLOT LINES: LOG10(f),DEG(ATN(Im(vv)/Re(vv)))/2; !位相θ ※1/2倍
NEXT f
PLOT LINES
END
!直接法による行列の固有値を求める
OPTION ARITHMETIC COMPLEX
LET i=SQR(-1) !虚数単位
LET cEps=1e-8 !誤差 ※単精度
LET N=3 !N次正方行列
FUNCTION tr(A(,)) !行列Aのトレース
LET t=0
FOR j=1 TO N
LET t=t+A(j,j)
NEXT j
LET tr=t
END FUNCTION
DIM c(N) !多項式 X^N+c(1)*X^(N-1)+c(2)*X^(N-2)+ … +c(N-1)*X+c(N) の係数
SUB DKA_00(A(),Xr()) !DKA法(Durand Kerner Aberth)
LET r=1 !初期値を仮定する
FOR j=2 TO N
LET rn=ABS(A(j))^(1/j)
if r<rn then LET r=rn
NEXT j
FOR j=1 TO N !半径rの円に等間隔に配置する
LET Xr(j)=-A(1)/N+r*EXP( 2*PI*i/N *(j-3/4) ) !アーバスの初期値
NEXT j
FOR m=0 TO 100 !反復 ※調整要
LET mfx=0
LET maj=0
FOR j=1 TO N
LET Xk=1
LET fx=1
FOR w=1 TO N
LET fx=fx*Xr(j)+A(w)
IF w<>j THEN LET Xk=Xk*(Xr(j)-Xr(w))
NEXT w
LET Xr(j)=Xr(j)-fx/Xk
IF mfx<ABS(fx) THEN LET mfx=ABS(fx)
IF maj<ABS(fx/Xk) THEN LET maj=ABS(fx/Xk)
NEXT j
IF mfx<cEps AND maj<cEps THEN EXIT FOR !収束したら
NEXT m
END SUB
!-------------------- ここまでがサブルーチン
DIM A(N,N) !行列A
!DATA 1,0,0 !λ=1(3重根)
!DATA 0,1,1
!DATA 0,0,1
!DATA 0,1,1 !λ=2,-1(重根)
!DATA 1,0,1
!DATA 1,1,0
!DATA 3,0,0 !λ=3,±i
!DATA 0,2,-5
!DATA 0,1,-2
DATA 2,1,-1 !λ=3,2,1
DATA 0,3,0
DATA 0,2,1
MAT READ A
MAT PRINT A;
!n次正方行列Aの固有多項式 det(tE-A)=t^n+c1*t^(n-1)+ … + cn を求める。
DIM X(N,N),cE(N,N)
MAT X=IDN !frame法
FOR k=1 TO N
MAT X=A*X
LET c(k)=-tr(X)/k
MAT cE=(c(k))*IDN
MAT X=X+cE
NEXT k
MAT PRINT c;
!ニュートン法などで解く。解が固有値になる。
DIM lmd(N)
CALL DKA_00(c,lmd)
FOR k=1 TO N
PRINT "固有値=";lmd(k)
NEXT k
!※N個求まった場合の検算
LET s=1
FOR k=1 TO N
LET s=s*lmd(k)
NEXT k
PRINT s, DET(A) !固有値の積=行列の行列式 Πλi=|A|
LET s=0
FOR k=1 TO N
LET s=s+lmd(k)
NEXT k
PRINT s, tr(A) !固有値の和=行列のトレース Σλi=trA
END
!継子立て(ヨセフスの問題)をシミュレートする
LET N=12 !石の数 ※
LET P=-3 !除いていく位置 ※<----------
LET a=4 !開始位置 ※<----------
!●数理的
IF P>0 THEN !時計まわりなら
PRINT MOD(a-1+f(N,P),N)+1
ELSE !反時計まわりなら
PRINT MOD((N-a)-1+f(N,ABS(P)),N)+1 !左右反転して時計まわりにする
END IF
PRINT
FUNCTION f(n,p) !1番から時計まわりにp番目を取り除く
IF n=1 THEN LET f=1 ELSE LET f=MOD(p-1+f(n-1,p),n)+1
END FUNCTION
!●シミュレータ
DIM s(N) !石の状態
FOR i=1 TO N !連番をつける
LET s(i)=i
NEXT i
SET WINDOW -2,2,-2,2 !表示画面
LET r=1.5 !石の位置
SET TEXT JUSTIFY "center","half" !文字の位置
LET r2=1.8
CALL disp_stone !初期状態
PRINT "開始位置=";a
PRINT "除いていく位置=";P
!LET s(a)=0
!CALL disp_stone
LET k=N !残りの個数
DO UNTIL k=1 !残りの石が1つになるまで
LET c=0 !カウンタ
DO UNTIL c=ABS(P) !該当位置を見つける
LET a=a+SGN(P) !±1 ※正の場合、時計まわり
LET b=MOD(a-1,N)+1 !配置位置を換算する
IF s(b)>0 THEN LET c=c+1 !石がある場合のみカウントする
LOOP
PRINT b !取り除く
LET s(b)=-1
LET k=k-1
CALL disp_stone !現在の状態
LOOP
SUB disp_stone !環状に並べる
SET DRAW mode hidden !ちらつきを抑える(開始)
CLEAR
FOR i=1 TO N
LET th=RAD(90-i/N*360) !Y軸から時計まわり
LET x=COS(th) !位置
LET y=SIN(th)
PLOT TEXT ,AT r2*x,r2*y: STR$(i) !番号
IF s(i)>=0 THEN DRAW disk WITH SCALE(0.1)*SHIFT(r*x,r*y) !石
NEXT i
SET DRAW mode explicit !ちらつきを抑える(終了)
WAIT DELAY 0.5
END SUB
END
LET N=4 !N行N列
LET a=-2 !折りたたむ位置(a,b)
LET b=2
DATA 0,1,1,0 !Qパターン ※1:表、0:裏
DATA 0,1,0,1
DATA 1,0,1,0
DATA 1,1,0,0
DIM M(N,N)
MAT READ M
FOR y=1 TO N !行
FOR x=1 TO N !列
IF MOD(ABS(x-a)+ABS(y-b),2)=1 THEN !格子上での距離 ※1:反転、0:そのまま
LET M(y,x)=1-M(y,x) !論理否定
END IF
PRINT M(y,x); !「0が4つ」または「1が4つ」の位置
NEXT x
PRINT
NEXT y
END
DECLARE EXTERNAL SUB combination
LET k=100000 ! 対戦回数
LET p=2 ! パターン
LET n=4 ! サイコロの種類
LET f=6 ! サイコロの面数
INPUT PROMPT "対戦人数は? " : r
IF r<2 OR r>n THEN STOP
DIM code$(p,n),dice(p,n,f),d(r),win(r),sumwin(p,n),a(n),com(COMB(n,r),r)
MAT READ code$,dice
MAT a=ZER(n)
MAT sumwin=ZER
LET total=(COMB(n,r)-COMB(n-1,r))*k
LET count=0 ! COMB(n,r)
CALL combination(a,n,1,r,com,count)
FOR pp=1 TO p
FOR i=1 TO count
MAT win=ZER
FOR j=1 TO k
LET maxd=-1
FOR ri=1 TO r
LET d(ri)=dice(pp,com(i,ri),INT(f*RND)+1)
IF d(ri)>maxd THEN
LET maxd=d(ri)
LET w=ri
ELSEIF d(ri)=maxd THEN ! 引き分け
LET w=0
END IF
NEXT ri
IF w=0 THEN LET j=j-1 ELSE LET win(w)=win(w)+1
NEXT j
LET maxw=0
FOR ri=1 TO r
LET sumwin(pp,com(i,ri))=sumwin(pp,com(i,ri))+win(ri)
PRINT code$(pp,com(i,ri));win(ri);" ";
IF win(ri)>maxw THEN
LET w=ri
LET maxw=win(ri)
END IF
NEXT ri
PRINT "勝者 ";code$(pp,com(i,w));win(w);"勝";k-win(w);"敗";
PRINT USING " 期待値 #.####":r*win(w)/k
NEXT i
PRINT "総合勝敗"
FOR ni=1 TO n
PRINT code$(pp,ni);sumwin(pp,ni);"勝";total-sumwin(pp,ni);"敗";
PRINT USING " 期待値 #.####":r*sumwin(pp,ni)/total
NEXT ni
PRINT
NEXT pp
DATA A,B,C,D,X,Y,Z,W
DATA 2,3,3,9,10,11 ! A
DATA 0,1,7,8,8,8 ! B
DATA 5,5,6,6,6,6 ! C
DATA 4,4,4,4,12,12 ! D
DATA 5,5,6,6,7,7 ! X
DATA 1,2,3,9,10,11 ! Y
DATA 0,1,7,8,8,9 ! Z
DATA 3,4,4,5,11,12 ! W
END
REM 十進BASIC添付"\BASICw32\SAMPLE\COMBINAT.BAS"より
REM 1〜nの集合からr個を選ぶ組合せを生成する。配列com(,)
EXTERNAL SUB combination(a(),n,k,r,com(,),count)
! k以降の数からr個を選択する
IF r=0 THEN
LET count=count+1
LET ri=1
FOR i=1 TO n
IF a(i)=1 THEN
LET com(count,ri)=i
LET ri=ri+1
END IF
NEXT i
ELSE
FOR i=k TO n-r+1
LET a(i)=1
CALL combination(a,n,i+1,r-1,com,count)
LET a(i)=0
NEXT i
END IF
END SUB
!打順考察のためのシミュレーション
DATA 0.2, 0.2, 0.3, 0.3, 0.3, 0.2, 0.2, 0.1, 0.1
!DATA 0.1, 0.2, 0.2, 0.3, 0.2, 0.1, 0.3, 0.2, 0.3
!DATA 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2
DIM D(9) !9人分の打率
MAT READ D
RANDOMIZE
LET N=5000 !試合数
FOR x=1 TO N
DIM SM(N) !総合得点
LET P=1 !打順
FOR w=1 TO 9 !9回まで
LET B=0 !塁の状態
LET S1=0 !得点
LET O=0
DO UNTIL O=3 !3アウトまで
!PRINT P;"番打者:";
IF RND<D(P) THEN !ヒットなら
LET t=INT(RND*10)+1 !長打率など ※1〜10
SELECT CASE t
CASE 1,2,3,4
LET v=1
CASE 5,6,7
LET v=2
CASE 8,9
LET v=3
CASE ELSE
LET v=4
END SELECT
!PRINT v;"塁打", !1〜4
LET B=B*10+1 !v塁打で走者を送る
LET S1=S1+INT(B/10^3)
LET B=MOD(B,10^3)
FOR i=0 TO v-2
LET B=B*10
LET S1=S1+INT(B/10^3)
LET B=MOD(B,10^3)
NEXT i
ELSE
LET O=O+1
!PRINT "アウト",
END IF
!PRINT USING "# %%%": S1,B !塁の状態
LET P=P+1 !次へ
IF P>9 THEN LET P=1
LOOP
!PRINT w;"回";S1;"点"
!PRINT
LET SM(w)=SM(w)+S1
NEXT w
NEXT x
LET S=0 !得点の分布
FOR w=1 TO 9
PRINT w;"回";SM(w)/N;"点"
LET S=S+SM(w)
NEXT w
PRINT "総合得点=";S/N
END
DECLARE EXTERNAL SUB perm
PUBLIC NUMERIC player,games,rank,total_point,worst_point
PUBLIC NUMERIC ave(9),best_order(100,9),best_point(100)
PRINT TIME$
LET t=TIME
LET player=9 ! 9!=362880通り
LET games=1000 ! 試合数
LET rank=100 ! ランク
MAT READ ave
DATA .460,.420,.380,.340,.300,.260,.220,.180,.140
!DATA .380,.360,.340,.320,.300,.280,.260,.240,.220
DIM a(player)
FOR i=1 TO player
LET a(i)=i
NEXT i
MAT best_order=ZER
MAT best_point=ZER
LET total_point=0
LET worst_point=10*games
CALL perm(a,1)
FOR i=1 TO rank
PRINT USING "No## 打順" : i;
FOR j=1 TO player
PRINT best_order(i,j);
NEXT j
PRINT USING " 期待値-%.### 点":best_point(i)/games
NEXT i
PRINT "最低期待値 =";worst_point/games;"点"
PRINT "平均 =";total_point/(games*FACT(player));"点"
PRINT TIME-t;"sec"
END
EXTERNAL SUB simulation(order())
LET sum_point=0
FOR i=1 TO games
LET at_bat=0
FOR inning=1 TO 9 ! 9回
LET out_count=0
LET hit=0
DO
IF ave(order(MOD(at_bat,player)+1))>RND THEN
LET hit=hit+1
IF hit>=3 THEN LET sum_point=sum_point+1
ELSE
LET out_count=out_count+1
END IF
LET at_bat=at_bat+1
LOOP UNTIL out_count=3
NEXT inning
NEXT i
LET total_point=total_point+sum_point
IF sum_point>best_point(rank) THEN ! ランク付け
LET best_point(rank)=sum_point
FOR j=1 TO player
LET best_order(rank,j)=order(j)
NEXT j
FOR i=rank TO 2 STEP -1
IF best_point(i)>best_point(i-1) THEN
SWAP best_point(i),best_point(i-1)
FOR j=1 TO player
SWAP best_order(i,j),best_order(i-1,j)
NEXT j
ELSE
EXIT SUB
END IF
NEXT i
ELSEIF sum_point<worst_point THEN
LET worst_point=sum_point
END IF
END SUB
REM 十進BASIC添付"\BASICw32\SAMPLE\PERMUTAT.BAS"より
REM 1〜nの順列を辞書式順序で生成する。
EXTERNAL SUB perm(a(),n)
DECLARE EXTERNAL SUB simulation
IF n=player THEN
CALL simulation(a)
ELSE
FOR i=n TO player
LET t=a(i)
FOR j=i-1 TO n STEP -1
LET a(j+1)=a(j)
NEXT j
LET a(n)=t
CALL perm(a,n+1)
LET t=a(n)
FOR j=n TO i-1
LET a(j)=a(j+1)
NEXT j
LET a(i)=t
NEXT i
END IF
END SUB
! euler function
!------------------
INPUT PROMPT "n=":M
LET Mw=M
LET Phi=1
DO
LET P=prmdiv(Mw)
LET Phi=Phi*(P-1)
LET Mw=INT(Mw/P)
DO WHILE MOD(Mw,P)=0
LET Phi=Phi*P
LET Mw=INT(Mw/P)
LOOP
LOOP UNTIL Mw=1
PRINT Phi
FUNCTION prmdiv(Mw) !1<の最小の約数
FOR i=2 TO Mw
IF MOD(Mw,i)=0 THEN EXIT FOR
NEXT i
LET prmdiv=i
END FUNCTION
> FUNCTION prmdiv(Mw) !1<の最小の約数
> FOR i=2 TO Mw
> IF MOD(Mw,i)=0 THEN EXIT FOR
> NEXT i
> LET prmdiv=i
> END FUNCTION
関数定義を改良しました。
引数が大きく、最小の約数も大きいとき効果があります。
FUNCTION prmdiv(Mw) !1<の最小の約数
IF MOD(Mw,2)=0 THEN
LET prmdiv=2
EXIT FUNCTION
ELSEIF MOD(Mw,3)=0 THEN
LET prmdiv=3
EXIT FUNCTION
END IF
FOR i=5 TO SQR(Mw) STEP 6
IF MOD(Mw,i)=0 THEN
LET prmdiv=i
EXIT FUNCTION
ELSEIF MOD(Mw,i+2)=0 THEN
LET prmdiv=i+2
EXIT FUNCTION
END IF
NEXT i
LET prmdiv=Mw
END FUNCTION
!べき乗法による行列の固有値と固有ベクトルを求める
!※固有値が0、重複する場合は適用できない。
!※実数の固有値のみ。虚数を含む解は得られない。
!Ax=λIx、λ:固有値、x:固有ベクトル
LET N=3 !N次正方行列
DATA 2,1,-1 !λ=3,2,1
DATA 0,3,0
DATA 0,2,1
!DATA 0,1,1 !λ=2,1,0
!DATA -4,4,2
!DATA 4,-3,-1
!DATA 1,0,0 !λ=1(3重根)
!DATA 0,1,1
!DATA 0,0,1
DIM A(N,N) !行列A
MAT READ A
MAT PRINT A;
LET cEps=1e-6 !誤差 ※調整要、単精度
DIM u(N) !固有ベクトル
DIM AA(N,N) !作業用
MAT AA=A
FOR s=1 TO N !s番目
CALL EigenPower(N,AA, lambda,u)
PRINT "固有値=";lambda
PRINT "固有ベクトル"
MAT PRINT u;
FOR i=1 TO N !残差行列を求めて、次へ
FOR j=1 TO N
LET AA(i,j)=AA(i,j)-lambda*u(i)*u(j)
NEXT j
NEXT i
NEXT s
DEF norm(v())=SQR(DOT(v,v)) !ノルム
SUB EigenPower(N,A(,), lambda,u()) !固有値(絶対値最大)、固有ベクトルを求める
DIM u0(100),u2(100) !※最大100次
MAT u=CON !初期値 ※ノルムが1
MAT u=(1/norm(u))*u
LET cMax=100
FOR i=1 TO cMax !最大回数まで繰り返す
MAT u0=u !直前のu
MAT u=A*u0
WHEN EXCEPTION IN
MAT u=(1/norm(u))*u !正規化する
USE
PRINT "0ベクトルになりました。"
STOP
END WHEN
MAT u2=u-u0 !収束したか確認する
IF norm(u2)<cEps THEN EXIT FOR
MAT u2=u+u0
IF norm(u2)<cEps THEN EXIT FOR
NEXT i
IF i>cMax THEN
PRINT "収束しません。"
STOP
END IF
MAT u2=A*u
LET lambda=DOT(u2,u)/DOT(u,u) !固有値
END SUB
END
!打順考察のためのシミュレーション
DATA 0.2, 0.2, 0.3, 0.3, 0.3, 0.2, 0.2, 0.1, 0.1
!DATA 0.1, 0.2, 0.2, 0.3, 0.2, 0.1, 0.3, 0.2, 0.3
!DATA 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2
DIM D(9) !9人分の打率
MAT READ D
RANDOMIZE
LET N=10 !試合数 ※調整要
FOR x=1 TO N
PRINT !<----- ここ
PRINT "***";x;"試合目 ***" !<----- ここ
DIM SM(N) !総合得点
LET P=1 !打順
FOR w=1 TO 9 !9回まで
LET B=0 !塁の状態
LET S1=0 !得点
LET O=0
DO UNTIL O=3 !3アウトまで
PRINT P;"番打者:"; !<----- ここ
IF RND<D(P) THEN !ヒットなら
LET t=INT(RND*10)+1 !長打率など ※1〜10
SELECT CASE t
CASE 1,2,3,4
LET v=1
CASE 5,6,7
LET v=2
CASE 8,9
LET v=3
CASE ELSE
LET v=4
END SELECT
PRINT v;"塁打", !1〜4 <----- ここ
LET B=B*10+1 !v塁打で走者を送る
LET S1=S1+INT(B/10^3)
LET B=MOD(B,10^3)
FOR i=0 TO v-2
LET B=B*10
LET S1=S1+INT(B/10^3)
LET B=MOD(B,10^3)
NEXT i
ELSE
LET O=O+1
PRINT "アウト", !<----- ここ
END IF
PRINT USING "# %%%": S1,B !塁の状態 <----- ここ
LET P=P+1 !次へ
IF P>9 THEN LET P=1
LOOP
PRINT w;"回";S1;"点" !<----- ここ
PRINT !<----- ここ
LET SM(w)=SM(w)+S1
NEXT w
NEXT x
PRINT
LET S=0 !得点の分布
FOR w=1 TO 9
PRINT w;"回";SM(w)/N;"点"
LET S=S+SM(w)
NEXT w
PRINT "総合得点=";S/N
END
DEF f(x)=x^2 !関数y=x^2
DEF g(x,a,b)=(f(b)-f(a))/(b-a)*(x-a)+f(a) !点Aと点Bを通る直線
LET a=-2
LET b=4
SET bitmap SIZE 300,600
SET WINDOW -10,10,-20,20 !表示領域
DRAW grid !座標
FOR x=-10 TO 10 STEP 0.2 !放物線y=x^2を描く
PLOT LINES: x,f(x);
NEXT x
PLOT LINES
SUB ten(x,y,s$)
PLOT TEXT ,AT x+0.4,y: s$
DRAW disk WITH SCALE(0.2)*SHIFT(x,y)
END SUB
CALL ten(-a,f(-a),"A")
CALL ten(b,f(b),"B")
FOR x=-10 TO 10 STEP 0.2 !直線を描く
PLOT LINES: x,g(x,-a,b);
NEXT x
PLOT LINES
CALL ten(0,g(0,-a,b),"P") !y切片
PRINT g(0,-a,b), a*b !検算
DEF h(a,b)=(f(b)-f(a))/(b-a) !傾き
PRINT h(a,b), a+b
END
10 DEF f(x)=x^2 !関数y=x^2
20 DEF g(x,a,b)=(f(b)-f(a))/(b-a)*(x-a)+f(a) !点Aと点Bを通る直線
30 INPUT PROMPT "2数を選ぶ":x,y
40 LET x1=INT(LOG10(x))
50 LET y1=INT(LOG10(y))
60 LET x=x/10^x1
70 LET y=y/10^y1
80 LET a=x
90 LET b=y
100 IF a>b THEN LET t=a ELSE LET t=b
110 SET bitmap SIZE 300,600
120 SET WINDOW -(t+1),t+1,-2,(t+1)^2+5 !表示領域
130 DRAW grid !座標
140 FOR x=-10 TO 10 STEP 0.2 !放物線y=x^2を描く
150 PLOT LINES: x,f(x);
160 NEXT x
170 PLOT LINES
180 SUB ten(x,y,s$)
190 PLOT TEXT ,AT x+0.4,y: s$
200 DRAW disk WITH SCALE(0.2)*SHIFT(x,y)
210 END SUB
220 CALL ten(-a,f(-a),"A")
230 CALL ten(b,f(b),"B")
240 FOR x=-10 TO 10 STEP 0.2 !直線を描く
250 PLOT LINES: x,g(x,-a,b);
260 NEXT x
270 PLOT LINES
280 CALL ten(0,g(0,-a,b),"P") !y切片
290 PRINT "Y切片の値";g(0,-a,b);
300 PRINT "計算結果"; a*b*10^(x1+y1) !検算
310 DEF h(a,b)=(f(b)-f(a))/(b-a) !傾き
320 !PRINT h(a,b), a+b
330 END
!RSA公開鍵暗号の計算
PRINT modpow(1371,1241,2279) !1371を暗号化する。公開鍵43*53=2279と1241
PRINT eul(2279) !=2184、43と53と2184は秘密
PRINT gcd(43,53) !互いに素
PRINT gcd(2184,1241) !互いに素
PRINT modinv(1241,2184) !秘密鍵1649
PRINT modpow(2003,1649,2279) !2003を複合化する
!nの1より大きな最小の約数
PRINT prmdiv(1234567) !127
PRINT prmdiv(23456789) !23456789
!PRINT prmdiv(11111111111111111) !2071723
!素数の生成
PRINT prm(100) !541
PRINT nxtprm(999) !prm(1000)=7919
!PRINT nxtprm(9999) !prm(10000)=104729
!オイラー関数(1からnまでの自然数のうちnと互いに素なものの個数)
FOR N=2 TO 100
LET S=0
FOR i=1 TO N-1
IF GCD(N,i)=1 THEN LET S=S+1
NEXT i
PRINT N;S, eul(N)
NEXT N
FOR i=2 TO 100
PRINT USING "#### #### #### ####": i,fnSigma(i),eul(i),moeb(i)
NEXT i
END
!整数論関連 ※ubasicより
EXTERNAL FUNCTION prmdiv(n) !1より大きな最小の約数
IF MOD(n,2)=0 THEN !2の倍数
LET prmdiv=2
ELSEIF MOD(n,3)=0 THEN !3の倍数
LET prmdiv=3
ELSE
FOR i=5 TO SQR(n) STEP 6
!!!FOR i=5 TO INTSQR(n) STEP 6 !<----- ※有理数モード
IF MOD(n,i)=0 THEN !5,11,17,23,29,…
LET prmdiv=i
EXIT FUNCTION
ELSEIF MOD(n,i+2)=0 THEN !7,13,19,25,31,…
LET prmdiv=i+2
EXIT FUNCTION
END IF
NEXT i
LET prmdiv=n !その数自身
END IF
END FUNCTION
EXTERNAL FUNCTION eul(n) !オイラー関数 φ(n)(1からnまでの自然数のうちnと互いに素なものの個数)
LET t=n
IF MOD(n,2)=0 THEN
LET t=t/2
DO
LET n=n/2
LOOP WHILE MOD(n,2)=0
END IF
LET d=3
DO WHILE n/d>=d
IF MOD(n,d)=0 THEN
LET t=t/d*(d-1)
DO
LET n=n/d
LOOP WHILE MOD(n,d)=0
END IF
LET d=d+2
LOOP
IF n>1 THEN LET t=t/n*(n-1)
LET eul=t
END FUNCTION
EXTERNAL FUNCTION moeb(n) !メビウス関数 μ(n)
LET W=1
DO WHILE n>1
LET P=prmdiv(n)
IF MOD(n,P^2)=0 THEN
LET W=0
EXIT DO
END IF
LET W=-W
LET n=INT(n/P)
LOOP
LET moeb=W
END FUNCTION
EXTERNAL FUNCTION modpow(a,b,n) !a^b≡x mod n のxを返す
IF b=0 THEN
LET modpow=1
ELSE
LET S=1
DO WHILE b>0
IF MOD(b,2)=1 THEN LET S=MOD(S*a,n) !ビットが1なら計算する
LET b=INT(b/2) !べき乗bを2進展開する
LET a=MOD(a*a,n)
LOOP
END IF
LET modpow=S
END FUNCTION
EXTERNAL FUNCTION modinv(a,n) !nを法としたaの逆元 a*x (mod n)=1
LET M=n
LET Sa=1
LET Ta=0
DO WHILE M<>0
LET Q=INT(a/M)
LET U=a-Q*M
LET Ua=Sa-Q*Ta
LET a=M
LET Sa=Ta
LET M=U
LET Ta=Ua
LOOP
IF a<>1 THEN
LET modinv=0
ELSE
IF Sa<0 THEN LET Sa=Sa+n
LET modinv=Sa
END IF
END FUNCTION
EXTERNAL FUNCTION prm(n) !n番目の素数 ※nは1以上
DIM prime(n) !素数列
LET prime(1)=2 !1番目は2
LET k=2 !k番目
LET x=1 !検証する自然数
DO WHILE k<=n !N番目まで
LET x=x+2 !奇数が対象
LET j=1 !見つかった素数の倍数かどうか確認する
DO WHILE j<k AND MOD(x,prime(j))<>0 !倍数なら途中で終了
LET j=j+1
LOOP
IF j=k THEN !新しく見つかった素数を記録する
LET prime(k)=x
LET k=k+1
END IF
LOOP
LET prm=prime(n)
END FUNCTION
EXTERNAL FUNCTION nxtprm(n) !n+1番目の素数
LET nxtprm=prm(n+1)
END FUNCTION
EXTERNAL FUNCTION gcd(a,b) !最大公約数
DO UNTIL b=0
LET t=b
LET b=MOD(a,b)
LET a=t
LOOP
LET gcd=a
END FUNCTION
EXTERNAL FUNCTION lcm(a,b) !最小公倍数
LET lcm=a*b/gcd(a,b)
END FUNCTION
!ユーザー定義
EXTERNAL FUNCTION fnSigma(n) !約数の和 σ(n)
LET S=1
DO WHILE n>1
LET W=1
LET P=prmdiv(n)
DO
LET W=W*P+1
LET n=INT(n/P)
LOOP WHILE MOD(n,P)=0
LET S=S*W
LOOP
LET fnSigma=S
END FUNCTION
> !素数の生成
> PRINT prm(100) !541
> PRINT nxtprm(999) !prm(1000)=7919
> !PRINT nxtprm(9999) !prm(10000)=104729
>
> EXTERNAL FUNCTION prm(n) !n番目の素数 ※nは1以上
> DIM prime(n) !素数列
> LET prime(1)=2 !1番目は2
> LET k=2 !k番目
> LET x=1 !検証する自然数
> DO WHILE k<=n !N番目まで
> LET x=x+2 !奇数が対象
> LET j=1 !見つかった素数の倍数かどうか確認する
> DO WHILE j<k AND MOD(x,prime(j))<>0 !倍数なら途中で終了
> LET j=j+1
> LOOP
> IF j=k THEN !新しく見つかった素数を記録する
> LET prime(k)=x
> LET k=k+1
> END IF
> LOOP
> LET prm=prime(n)
> END FUNCTION
>
> EXTERNAL FUNCTION nxtprm(n) !n+1番目の素数
> LET nxtprm=prm(n+1)
> END FUNCTION
EXTERNAL FUNCTION prm(n) ! n番目の素数
DIM prime(n)
FOR i=1 TO MIN(n,10)
READ prime(i)
NEXT i
DATA 2,3,5,7,11,13,17,19,23,29
FOR i=11 TO n
LET m30=MOD(prime(i-1),30)
IF m30=1 OR m30=23 THEN LET a=prime(i-1)+6 ELSE LET a=prime(i-1)-2*MOD(m30,3)+6
DO
LET sqra=SQR(a)
FOR j=4 TO i-1
IF MOD(a,prime(j))=0 THEN EXIT FOR
IF prime(j)>=sqra THEN
LET prime(i)=a
EXIT DO
END IF
NEXT j
LET m30=MOD(a,30)
IF m30=1 OR m30=23 THEN LET a=a+6 ELSE LET a=a-2*MOD(m30,3)+6
LOOP
NEXT i
LET prm=prime(n)
END FUNCTION
EXTERNAL FUNCTION nxtprm(x) !xより大きい素数の最小のもの
DIM prime(x)
FOR i=1 TO 10 !最初の10個
READ prime(i)
IF x<prime(i) THEN
LET nxtprm=prime(i)
EXIT FUNCTION
END IF
NEXT i
DATA 2,3,5,7,11,13,17,19,23,29
FOR i=11 TO INT(x) !11個目以降
LET m30=MOD(prime(i-1),30)
IF m30=1 OR m30=23 THEN LET a=prime(i-1)+6 ELSE LET a=prime(i-1)-2*MOD(m30,3)+6
DO
LET sqra=SQR(a)
!!!LET sqra=INTSQR(a) !<----- ※有理数モード
FOR j=4 TO i-1
IF MOD(a,prime(j))=0 THEN EXIT FOR
IF prime(j)>=sqra THEN
LET prime(i)=a
EXIT DO
END IF
NEXT j
LET m30=MOD(a,30)
IF m30=1 OR m30=23 THEN LET a=a+6 ELSE LET a=a-2*MOD(m30,3)+6
LOOP
IF x<prime(i) THEN
LET nxtprm=prime(i)
EXIT FUNCTION
END IF
NEXT i
PRINT "見つかりません。"
STOP
END FUNCTION
●prm(n)関数を使ったものを追加しておきます。(定義済みのサブルーチンは省略)
!素数の個数
!PRINT fnPrimePi(77777)
!原始根 genshi3
FOR LP=1 TO 100
LET P=prm(LP) !最初の100個の素数に対して
PRINT USING "##### ### |": P,fnGenshi(P);
IF MOD(LP,5)=0 THEN PRINT
NEXT LP
PRINT
!原始根 genshi2
FOR LP=1 TO 100
LET P=prm(LP) !最初の100個の素数に対して
LET G=1
IF P<>2 THEN
50 LET G=G+1
LET W=1
FOR i=1 TO P-2
LET W=MOD(W*G,P)
IF W=1 THEN GOTO 50
NEXT i
END IF
PRINT USING "##### ### |": P,G;
IF MOD(LP,5)=0 THEN PRINT
NEXT LP
PRINT
END
EXTERNAL FUNCTION fnPrimePi(X) !実数xに対しx以下の素数の個数
LET S=1
LET E=10000 !100,000以下の素数は10,000個未満だから ※
DO WHILE E>S+1
LET K=INT((S+E)/2) !2分探索
IF prm(K)<=X THEN LET S=K ELSE LET E=K
LOOP
LET fnPrimePi=S
END FUNCTION
EXTERNAL FUNCTION fnGenshi(P) !原始根
LET G=1
LET N=P-1
IF P<>2 THEN
180 LET G=G+1
LET Nw=N
DO
LET Div=prmdiv(Nw)
DO WHILE MOD(Nw,Div)=0
LET Nw=INT(Nw/Div)
LOOP
IF modpow(G,INT(N/Div),P)=1 THEN GOTO 180
LOOP UNTIL Nw=1
END IF
LET fnGenshi=G
END FUNCTION
! MAZE.UB
!---------------------------------
! 迷路を作る
! Pascal version from
! 奥村晴彦 コンピュータアルゴリズム事典(技術評論社) 349-350
! 〔付〕迷路を解く by 岩瀬順一
OPTION BASE 0
SET WINDOW 0,500, 500,0
!
LET Xmax=90
LET Ymax=90
LET MaxCan=INT(Xmax*Ymax/4) ! must Ymax<=Xmax
LET Bsize=4
LET Xoff=INT((500-Xmax*Bsize)/2)
LET Yoff=INT((500-Ymax*Bsize)/3) ! 20
DIM Map_(Xmax,Ymax)
DIM CanX_(MaxCan),CanY_(MaxCan),DirX_(MaxCan),DirY_(MaxCan)
RANDOMIZE
!
FOR I=0 TO 1
FOR J=0 TO Ymax
LET Map_(I,J)=1
LET Map_(Xmax-I,J)=1
NEXT J
NEXT I
FOR J=0 TO 1
FOR I=0 TO Xmax
LET Map_(I,J)=1
LET Map_(I,Ymax-J)=1
NEXT I
NEXT J
LET X=2
FOR Y=4 TO Ymax-2
CALL DOT_(X,Y)
NEXT Y
LET X=Xmax-2
FOR Y=2 TO Ymax-4
CALL DOT_(X,Y)
NEXT Y
LET Y=2
FOR X=2 TO Xmax-2
CALL DOT_(X,Y)
NEXT X
LET Y=Ymax-2
FOR X=2 TO Xmax-2
CALL DOT_(X,Y)
NEXT X
LET Ncan=0
FOR I=2 TO INT(Xmax/(2)) -2
CALL InsCan_(I*2,2)
CALL InsCan_(I*2,Ymax-2)
NEXT I
FOR J=2 TO INT(Ymax/(2)) -2
CALL InsCan_(2,J*2)
CALL InsCan_(Xmax-2,J*2)
NEXT J
LET Ndir=4
LET DirX_(1)=2
LET DirY_(1)=0
LET DirX_(2)=0
LET DirY_(2)=2
LET DirX_(3)=-2
LET DirY_(3)=0
LET DirX_(4)=0
LET DirY_(4)=-2
DO WHILE Ncan>0
CALL Selcan_(I,J)
DO
LET Ndir=4
DO
CALL SelDir_(DI,DJ)
LET Ok=1-Map_(I+DI,J+DJ)
LOOP UNTIL Ok<>0 OR Ndir=0
IF Ok<>0 THEN
CALL DOT_(I+INT(DI/(2)),J+INT(DJ/(2)) )
LET I=I+DI
LET J=J+DJ
CALL DOT_(I,J)
CALL InsCan_(I,J)
END IF
LOOP UNTIL NOT Ok<>0
LOOP
SUB DOT_(X,Y)
LET Map_(X,Y)=1
! SET AREA COLOR 5
PLOT AREA:
Bsize*X+Xoff,Bsize*Y+Yoff;Bsize*X+Xoff+Bsize-1,Bsize*Y+Yoff;Bsize*X+Xoff+Bsize-1,Bsize*Y+Yoff+Bsize-1;Bsize*X+Xoff,Bsize*Y+Yoff+Bsize-1
END SUB
SUB InsCan_(I,J)
LET Ncan=Ncan+1
LET CanX_(Ncan)=I
LET CanY_(Ncan)=J
END SUB
SUB Selcan_(I,J)
local R
LET R=int(Ncan*rnd)+1
LET I=CanX_(R)
LET J=CanY_(R)
LET CanX_(R)=CanX_(Ncan)
LET CanY_(R)=CanY_(Ncan)
LET Ncan=Ncan-1
END SUB
SUB SelDir_(I,J)
local R
LET R=int(Ndir*rnd)+1
LET I=DirX_(R)
LET J=DirY_(R)
LET DirX_(R)=DirX_(Ndir)
LET DirY_(R)=DirY_(Ndir)
LET DirX_(Ndir)=I
LET DirY_(Ndir)=J
LET Ndir=Ndir-1
END SUB
!--------------------------------------------------
! この先は、岩瀬が書いた。
! 方針:袋小路があったら、ぬりつぶす
!
PLOT TEXT,AT Xoff*1.2,20 :"何かキーを押してください。迷路を解きます。"
PLOT TEXT,AT Xoff*1.2,40 :"Push any key to solve the maze."
CHARACTER INPUT s$
SET AREA COLOR 0
PLOT AREA :Xoff,0; 500,0; 500,40; Xoff,40
!
LET Map_(2,3)=0
LET Map_(Xmax-2,Ymax-3)=0 ! 出口、入口は0にする
FOR I=0 TO Xmax ! 迷路の外は1にする
FOR J=0 TO 1
LET Map_(I,J)=0
NEXT J
FOR J=Ymax-1 TO Ymax
LET Map_(I,J)=0
NEXT J
NEXT I
FOR J=0 TO Ymax
FOR I=0 TO 1
LET Map_(I,J)=0
NEXT I
FOR I=Xmax-1 TO Xmax
LET Map_(I,J)=0
NEXT I
NEXT J
!
!
!$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
!$$$$$$$$$ MAIN ROUTINE TO SOLVE THE MAZE $$$$$$$$$$$$$$$$$$$$$$$$$$$
!$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
!
FOR K=6 TO Ymax
FOR J=3 TO K-3
CALL Routine_
NEXT J
NEXT K
FOR K=Ymax+1 TO Xmax
FOR J=3 TO Ymax-3
CALL Routine_
NEXT J
NEXT K
FOR K=Xmax+1 TO Xmax+Ymax-6
FOR J=K-Xmax+3 TO Ymax-3
CALL Routine_
NEXT J
NEXT K
SUB Routine_
LET I=K-J
IF fnCheck(I,J)< 3 THEN EXIT SUB
LET Ii=I
LET Jj=J
DO
CALL Fil_(Ii,Jj)
IF Map_(Ii-1,Jj)=0 THEN
LET Ii=Ii-1
ELSEIF Map_(Ii,Jj+1)=0 THEN
LET Jj=Jj+1
ELSEIF Map_(Ii+1,Jj)=0 THEN
LET Ii=Ii+1
ELSEIF Map_(Ii,Jj-1)=0 THEN
LET Jj=Jj-1
END IF
LOOP UNTIL fnCheck(Ii,Jj)<>3
END SUB
SUB Fil_(X,Y)
LET Map_(X,Y)=1
SET AREA COLOR 4 !3
PLOT AREA:
Bsize*X+Xoff,Bsize*Y+Yoff;Bsize*X+Xoff+Bsize-1,Bsize*Y+Yoff;Bsize*X+Xoff+Bsize-1,Bsize*Y+Yoff+Bsize-1;Bsize*X+Xoff,Bsize*Y+Yoff+Bsize-1
END SUB
FUNCTION fnCheck(I,J) ! 袋小路の時3をかえす
LET fnCheck=0
IF Map_(I,J)=1 THEN EXIT FUNCTION
LET fnCheck=Map_(I-1,J)+Map_(I,J+1)+Map_(I+1,J)+Map_(I,J-1)
END FUNCTION
DECLARE EXTERNAL SUB sort
PUBLIC NUMERIC c
LET tt=TIME
LET s=4
LET n=13
LET c=s*n
DIM check(c),card(c),position(n,s),face(n),total(0 TO n-1),count(0 TO n-1)
LET test=100000 ! 100000で125秒
FOR t=1 TO test
CALL prep
CALL play
NEXT t
LET cc=0
PRINT " 組 確率 平均枚数"
FOR i=0 TO n-1
PRINT USING " ## .##### ##.##枚" : i,total(i)/test,count(i)/total(i)
LET cc=cc+count(i)
NEXT i
PRINT USING " ##.##枚" : cc/test
PRINT INT(TIME-tt);"sec"
SUB prep
FOR i=1 TO c
LET check(i)=RND
NEXT i
CALL sort(check,card)
!MAT PRINT card;
FOR j=1 TO s
FOR i=1 TO n
LET position(i,j)=card((j-1)*n+i)
NEXT i
NEXT j
!MAT PRINT position;
END SUB
SUB play
MAT face=ZER
LET cc=0
CALL open_card(n)
!MAT PRINT face;
LET f=0
FOR i=1 TO n-1
IF face(i)=s THEN LET f=f+1
NEXT i
LET total(f)=total(f)+1
LET count(f)=count(f)+cc
END SUB
SUB open_card(nn)
LET cc=cc+1
LET look=position(nn,1)
FOR j=1 TO s-1
LET position(nn,j)=position(nn,j+1)
NEXT j
LET p=MOD(look,n)+1
!PRINT p;
LET face(p)=face(p)+1
IF face(n)=s THEN EXIT SUB
CALL open_card(p)
END SUB
END
REM 十進BASIC添付"\BASICw32\Library\SORT2.LIB"より
! ixにはmと下限,上限を一致させた空の配列を指定する。
! mは参照されるのみ。
! ixにmの添字を大きさの順に並べて返す。
! つまり,m(ix(1))≦m(ix(2))≦m(ix(3))≦・・・となる。
EXTERNAL SUB sort(m(),ix())
FOR i=1 TO c
LET ix(i)=i
NEXT i
CALL q_sort(m,ix,1,c)
END SUB
EXTERNAL SUB q_sort(m(),a(),l,r)
IF r<=l THEN
EXIT SUB
ELSE
LET i=l-1
LET j=r
LET pv=m(a(r))
DO
DO
LET i=i+1
LOOP UNTIL pv<=m(a(i))
DO
LET j=j-1
LOOP UNTIL j<=i OR m(a(j))<=pv
IF j<=i THEN EXIT DO
LET t=a(i)
LET a(i)=a(j)
LET a(j)=t
LOOP
LET t=a(i)
LET a(i)=a(r)
LET a(r)=t
CALL q_sort(m,a,l,i-1)
CALL q_sort(m,a,i+1,r)
END IF
END SUB
!アナログ時計
SET WINDOW -1.2,1.2,-1.2,1.2 !表示領域
SET TEXT JUSTIFY "center","half" !文字表示の書式
DO
LET t$=TIME$ !時刻をhh:mm:ss形式で得る
LET h=VAL(t$(1:2)) !数値へ
LET m=VAL(t$(4:5))
LET s=VAL(t$(7:8))
SET DRAW mode hidden !ちらつみ防止(開始)
CLEAR
FOR i=1 TO 12 !文字盤
LET th=PI/2-2*PI*i/12 !Y軸から時計まわり
PLOT TEXT ,AT COS(th),SIN(th): STR$(i) !円周上
NEXT i
LET th=PI/2-2*PI*(h + m/60)/12 !時針
PLOT LINES: 0,0; 0.6*COS(th),0.6*SIN(th)
LET th=PI/2-2*PI*m/60 !分針
PLOT LINES: 0,0; 0.9*COS(th),0.9*SIN(th)
LET th=PI/2-2*PI*s/60 !秒針
PLOT LINES: 0,0; 0.8*COS(th),0.8*SIN(th)
SET DRAW mode explicit !ちらつき防止(終了)
LOOP
END
上書きせていただきました。
調べたら1分間に約8200回の描画をしていたので、秒の更新があったときに描画するようにしました。
文字盤部分もLOOPから出して描画時間を節約。
長針・短針を絵定義にし、PICTURE hand を書き換えることにより針のデザイン変更を容易にできるようにしました。
!アナログ時計(改)
SET WINDOW -1.2,1.2,-1.2,1.2 !表示領域
SET TEXT JUSTIFY "center","half" !文字表示の書式
SET TEXT HEIGHT 1.2/10
SET AREA COLOR 5 ! 水色
SET POINT STYLE 4 ! 。
DRAW disk WITH SCALE(1.1)
FOR i=1 TO 12 !文字盤
LET th=PI/2-2*PI*i/12 !Y軸から時計まわり
PLOT TEXT ,AT COS(th),SIN(th): STR$(i) !円周上
FOR j=1 TO 4
LET th=PI/2-2*PI*(5*i+j)/60
PLOT POINTS : 0.94*COS(th),0.94*SIN(th)
NEXT j
NEXT i
SET LINE COLOR "RED"
LET t0=INT(TIME)
DRAW clock(t0)
DO
IF TIME-t0>=1 THEN ! 秒の更新で描画
LET t0=INT(TIME)
DRAW clock(t0)
END IF
LOOP
PICTURE clock(t0)
LET h=INT(t0/3600) !数値へ
LET m=INT((t0-3600*h)/60)
LET s=MOD(t0,60)
SET DRAW mode hidden !ちらつき防止(開始)
SET AREA COLOR 0 ! 白
DRAW disk WITH SCALE(0.9) !針描画部分のみクリア
LET th=PI/2-2*PI*(h + m/60)/12 !時針
DRAW hand(3) WITH SCALE(0.6,1)*ROTATE(th)
LET th=PI/2-2*PI*m/60 !分針
DRAW hand(2) WITH SCALE(0.86,1)*ROTATE(th)
LET th=PI/2-2*PI*s/60 !秒針
PLOT LINES: 0,0; 0.8*COS(th),0.8*SIN(th)
SET DRAW mode explicit !ちらつき防止(終了)
END PICTURE
PICTURE hand(col) !針描画
SET AREA COLOR col
PLOT AREA : -0.05,-0.03;1,-0.03;1,0.03;-0.05,0.03
END PICTURE
SET AREA COLOR 5
LET s00=SQR(3)/4
LET φ=0.001
LET stp=PI/180
DO
IF 2*PI<=ABS(φ) THEN LET stp=-stp ! (+)左回転 (−)右回転
LET φ=REMAINDER(φ, 2*PI) +stp
!-----
LET θ=φ+SIN(φ*51)*0.1+SIN(φ*49)*0.05 ! 水面揺れ..有り
!LET θ=φ ! 水面揺れ..無し
!-----
LET r=0.19985-0.00355*COS(θ*6) ! 液面補正、残誤差±3.85%
LET x00=0
LET y00=0
LET i=1
LET x(i)=x1(θ)
LET y(i)=y1
IF 0<=x(i) AND x(i)<=1 AND 0<=y(i) AND y(i)<=SQR(3)/2 THEN LET i=i+1
LET x(i)=x2(θ)
LET y(i)=y2(θ)
IF 0<=x(i) AND x(i)<=1 AND 0<=y(i) AND y(i)<=SQR(3)/2 THEN LET i=i+1.01
IF i< 3 THEN
LET x(i)=x3(θ)
LET y(i)=y3(θ)
IF 2< i THEN
LET x00=1/2
LET y00=SQR(3)/2
ELSE
LET x00=1
LET y00=0
END IF
END IF
LET ss2=ABS((x(1)-x00)*(y(2)-y00)-(y(1)-y00)*(x(2)-x00))
SET DRAW mode hidden
CLEAR
DRAW D4(3) WITH SHIFT(-1/2,-1/SQR(3)/2)*ROTATE(φ-PI/2)
DRAW center WITH SHIFT(-1/2,-1/SQR(3)/2)*ROTATE(-φ-PI/2)*SCALE(-1/8,1/8)
PLOT TEXT,AT 0.13,0.23:"右クリックで終了"
SET DRAW mode explicit
WAIT DELAY 0.05
MOUSE POLL mx,my,mlb,mrb
LOOP UNTIL mrb>=1
PICTURE center
SET LINE COLOR 2
SET LINE width 2
PLOT LINES:0,0;1,0;1/2,SQR(3)/2;0,0
SET LINE width 1
SET LINE COLOR 1
END PICTURE
!------
PICTURE D4(k)
IF 0< k THEN
DRAW D4(k-1) WITH SCALE(1/2,1/2)*SHIFT(1/4,SQR(3)/4) ! 上
DRAW D4(k-1) WITH SCALE(1/2,-1/2)*SHIFT(1/4,SQR(3)/4) ! 中
DRAW D4(k-1) WITH SCALE(1/2,1/2)*ROTATE(-PI*2/3)*SHIFT(1/4,SQR(3)/4) !左
DRAW D4(k-1) WITH SCALE(1/2,1/2)*ROTATE(PI*2/3)*SHIFT(1,0) ! 右
ELSE
DRAW Set01
END IF
END PICTURE
!------ 種の三角図
PICTURE Set01
IF s00< ss2 THEN
IF x00=0 THEN PLOT AREA:x(1),y(1);x(2),y(2);1/2,SQR(3)/2;1,0
IF x00=1 THEN PLOT AREA:x(1),y(1);x(2),y(2);1/2,SQR(3)/2;0,0
IF x00=1/2 THEN PLOT AREA:x(1),y(1);x(2),y(2);1,0;0,0
ELSE
PLOT AREA:x(1),y(1);x(2),y(2);x00,y00
END IF
PLOT LINES:x(1),y(1);x(2),y(2)
PLOT LINES:0,0;1,0;1/2,SQR(3)/2;0,0
END PICTURE
OPTION ARITHMETIC RATIONAL
LET t=fact(52)
LET s=0
FOR i=4 TO 52
LET b=perm(48,52-i) * 4 * fact(i-1) !残るカード、K、めくられていくカード(3枚のKを含む)
PRINT i;"枚 確率=";b/t
LET s=s+b/t
NEXT i
PRINT "確率=";s !検算
END
このプログラムは,a^n mod k を計算します。
kの値が8桁を超えるときは有理数モードで実行してください。
100 INPUT k
110 INPUT a,n
120 LET p=1
130 LET b=MOD(a,k)
140 DO UNTIL n=0
150 IF MOD(n,2)=1 THEN LET p=MOD(p*b,k)
160 LET b=MOD(b*b,k)
170 LET n=INT(n/2)
180 LOOP
190 PRINT p
200 END
DECLARE EXTERNAL SUB prime_factor
PUBLIC NUMERIC prn(2000000),pf(100),f
DECLARE FUNCTION modn
LET x=9876543201
LET n=1234567890
LET a=6789012345
LET r=MOD(x,a)
CALL prime_factor(n) ! 素因数分解
LET k=r
FOR i=1 TO f
LET k=modn(k,pf(i),a)
NEXT i
PRINT k
!
FUNCTION modn(r,n,a) ! mod(r^n,a)
LET kk=r
FOR ii=2 TO n
LET kk=MOD(kk*r,a)
NEXT ii
LET modn=kk
END FUNCTION
END
REM ** 素因数分解 **
EXTERNAL SUB prime_factor(n)
DECLARE EXTERNAL SUB prime
LET f=0 ! 素因数の個数
LET q=n ! qは、商
LET m=1 ! 検証用変数
FOR i=1 TO 10
READ prn(i)
NEXT i
DATA 2,3,5,7,11,13,17,19,23,29
LET i=1
DO WHILE MOD(q,prn(i))=0 ! 因数判定ルーチン
LET f=f+1
LET pf(f)=prn(i) ! pf(f)はnのf番目の素因数
LET q=q/prn(i)
LET m=m*prn(i)
LOOP
LET i=2
DO WHILE prn(i)<=SQR(q)
DO WHILE MOD(q,prn(i))=0 ! 因数判定ルーチン
LET f=f+1
LET pf(f)=prn(i) ! pf(f)はnのf番目の素因数
LET q=q/prn(i)
LET m=m*prn(i)
LOOP
IF q=1 THEN EXIT DO
LET i=i+1
IF i>10 THEN CALL prime(i) ! i番目の素数
LOOP
IF q<>1 THEN
LET f=f+1
LET pf(f)=q
LET m=m*q
END IF
IF m<>n THEN PRINT "error !!"
END SUB
!
REM ** 素数列生成(k番目の素数) **
EXTERNAL SUB prime(k)
LET m30=MOD(prn(k-1),30)
IF m30=1 OR m30=23 THEN LET a=prn(k-1)+6 ELSE LET a=prn(k-1)-2*MOD(m30,3)+6
DO
LET sqra=SQR(a)
FOR j=4 TO k-1
IF MOD(a,prn(j))=0 THEN EXIT FOR
IF prn(j)>=sqra THEN
LET prn(k)=a
EXIT SUB
END IF
NEXT j
LET m30=MOD(a,30)
IF m30=1 OR m30=23 THEN LET a=a+6 ELSE LET a=a-2*MOD(m30,3)+6
LOOP
END SUB
m回シャッフルを繰り返すと
f(f(f(…(f(k)))))=2*(2*(2*…(2*k mod n+1) mod n+1) mod n+1) mod n+1=2^m*k mod n+1
一覧表をつくるプログラム
!リフルシャッフル
!n枚のカードを1,2,3,…,n-1,nに並べる。
!1回のシャッフルでカードkが現れる位置をf(k)と表す。(カードkはf(k)番目にある)
DEF f(k)=MOD(2*k,n+1)
FOR n=2 TO 100 STEP 2 !偶数
PRINT USING "### 枚:":n;
LET x=1 !カードxに着目
LET iter=1000
FOR m=1 TO iter !m回のシャッフル ※
LET x=f(x) !2^m*k (mod n+1)
!!!PRINT m;x
IF x=n THEN PRINT USING "### 回目で逆順、":m; !逆順
IF x=1 THEN EXIT FOR !もとに戻る
NEXT m
IF m>iter THEN
PRINT USING "### 回では元に戻りません。":m
ELSE
PRINT USING "### 回目に元に戻る":m
END IF
NEXT n
END
UBASICのmodinv関数を使った場合(サブルーチンは省略)
FOR n=2 TO 100 STEP 2 !偶数
PRINT USING "### 枚:":n;
LET iter=1000
FOR m=1 TO iter
LET x=modinv(2^m,n+1) !1枚目のカードの元の位置を得る
IF x=n THEN PRINT USING "### 回目で逆順、":m; !逆順
IF x=1 THEN EXIT FOR !もとに戻る
NEXT m
IF m>iter THEN
PRINT USING "### 回では元に戻りません。":m
ELSE
PRINT USING "### 回目に元に戻る":m
END IF
NEXT n
END
> b=0 のときの値が変です。EXTERNAL FUNCTION modpow(a,b,n) !a^b≡x mod n のxを返す
b=0での場合分けは必要なしですね。(原形ではmodpow=1ではなくて、S=1でした。)
EXTERNAL FUNCTION modpow(a,b,n) !a^b≡x mod n のxを返す
LET S=1
DO WHILE b>0
IF MOD(b,2)=1 THEN LET S=MOD(S*a,n) !ビットが1なら計算する
LET b=INT(b/2) !べき乗bを2進展開する
LET a=MOD(a*a,n)
LOOP
LET modpow=S
END FUNCTION
!山を使ったシャッフル
LET p=3 !山の数
FOR n=p TO 100 STEP p !pの倍数
PRINT USING "### 枚:":n;
LET iter=1000
FOR m=1 TO iter
!!!LET x=modinv((n*p)^m,n+1) !1枚目のカードの元の位置(カード番号)を得る
LET x=modpow(n*p,m,n+1) !1番のカードの位置を得る
IF x=n THEN PRINT USING "### 回目で逆順、":m; !逆順
IF x=1 THEN EXIT FOR !もとに戻る
NEXT m
IF m>iter THEN
PRINT USING "##### 回では元に戻りません。":m
ELSE
PRINT USING "### 回目に元に戻る":m
END IF
NEXT n
END
!1つ覚えに過ぎるか?取りあえずミラーの中に入れてみた。plot text を避けて、
!plot label を使用したので、文字への効果は、ありません。
! 時計、時計、時計
!-------------------
LET N=2
LET NN=2^N
SET TEXT font "Century",11
SET TEXT JUSTIFY "center","half"
SET TEXT BACKGROUND "OPAQUE"
SET WINDOW -250/NN,250/NN,250/NN,-250/NN
LET φ=0
LET stp=-PI/180*6
DO
LET t=INT(TIME)
IF t0<>t THEN
LET t0=t
IF 2*PI<=ABS(φ) THEN LET stp=-stp
LET φ=REMAINDER(φ, 2*PI) +stp
!-----
SET DRAW mode hidden
CLEAR
DRAW D4(N) WITH SHIFT(-300/2,-300/2/SQR(3))*ROTATE(φ*(-1)^N)*SCALE(1,(-1)^N)
DRAW center WITH SHIFT(-300/2/NN,-300/2/NN/SQR(3))*ROTATE(φ)
PLOT TEXT,AT 180/NN,-240/NN:"Right Click to Stop"
SET DRAW mode explicit
ELSE
WAIT DELAY 0.05 ! 省電力効果
END IF
MOUSE POLL mx,my,mlb,mrb
LOOP UNTIL mrb>=1 ! 右クリックで停止
PICTURE center
SET LINE COLOR 2
SET LINE width 2
PLOT LINES:0,0;300/NN,0;300/2/NN,300/2/NN*SQR(3);0,0
SET LINE width 1
SET LINE COLOR 1
END PICTURE
!------
PICTURE D4(k)
IF 0< k THEN
DRAW D4(k-1) WITH SCALE(1/2,1/2)*SHIFT(300/4,SQR(3)*300/4) ! 内側の上
DRAW D4(k-1) WITH SCALE(1/2,-1/2)*SHIFT(300/4,SQR(3)*300/4) ! 内側の中
DRAW D4(k-1) WITH SCALE(1/2,1/2)*ROTATE(-PI*2/3)*SHIFT(300/4,SQR(3)*300/4) !内側の左
DRAW D4(k-1) WITH SCALE(1/2,1/2)*ROTATE(PI*2/3)*SHIFT(300,0) ! 内側の右
ELSE
DRAW 時計図 WITH ROTATE(-φ)*SHIFT(300/2,300/2/SQR(3))
PLOT LINES:0,0;300,0;300/2,SQR(3)*300/2;0,0 ! 外側の基準三角形(直接の描画は無し。)
END IF
END PICTURE
!------
PICTURE 時計図
SET AREA COLOR 1
FOR i=1 TO 60
LET a=PI/30*(i-15)
IF MOD(i,5)=0 THEN
PLOT label,AT 60*COS(a)+1, 60*SIN(a) :STR$(i/5) !数字
DRAW disk WITH SCALE(1)*SHIFT(72*COS(a),72*SIN(a)) !5分目盛り
ELSE
DRAW disk WITH SCALE(.5)*SHIFT(72*COS(a),72*SIN(a)) !1分目盛り
END IF
NEXT i
!--- 00:00 からt秒 の針回転 Gear
DRAW hand(1) WITH SCALE(2.5, 0.75)*ROTATE(t*PI/21600) ! 時針
DRAW hand(1) WITH ROTATE(t*PI/1800) ! 分針
DRAW hand(1) WITH SCALE(0, 1.1)*ROTATE(t*PI/30) ! 秒針
!--- 中心の飾り
DRAW disk WITH SHIFT(0,0)*SCALE(4)
END PICTURE
PICTURE hand(c) ! 3針共用
SET AREA COLOR c
PLOT AREA: -1,15; 1,15; 1,-60; -1,-60
END PICTURE
MAT READ px
DATA 0.20, 0.40, 0.60, 0.80, 0.70, 0.60, 0.50, 0.40, 0.30, 0.20, 0.40
MAT READ py
DATA 0.11, 0.11, 0.11, 0.11, 0.29, 0.47, 0.65, 0.47, 0.29, 0.11, 0.11
!----------
FOR N=0 TO 4
FOR s=9 TO 1 STEP -1
SET DRAW mode hidden
CLEAR
SET WINDOW -0.4,1.6, -1.1,0.9
PLOT TEXT,AT 0.6,0.8:"ミラー縮小4分岐"
PLOT TEXT,AT 0.8,0.7, USING "N= %%":N
DRAW D4(N)
SET WINDOW -1.0,1.0, -0.05,1.95
PLOT TEXT,AT 0.6,0.8:"中を抜いたもの"
PLOT TEXT,AT 0.8,0.7, USING "N= %%":N
DRAW D42(N)
SET WINDOW 0.0,4.0, -0.1,3.9
PLOT TEXT,AT 0.1,1.8:"シルピンスキーのガスケット"
PLOT TEXT,AT 1.2,1.6, USING "N= %%":N
DRAW D3(N)
SET DRAW mode explicit
WAIT DELAY 0.2
NEXT s
NEXT N
!------ ミラー縮小4分岐
PICTURE D4(k)
IF 0<k THEN
DRAW D4(k-1) WITH SCALE(1/2,1/2)*SHIFT(1/4,SQR(3)/4) ! 上
DRAW D4(k-1) WITH SCALE(1/2,-1/2)*SHIFT(1/4,SQR(3)/4) ! 中
DRAW D4(k-1) WITH SCALE(1/2,1/2)*ROTATE(-PI*2/3)*SHIFT(1/4,SQR(3)/4) ! 左
DRAW D4(k-1) WITH SCALE(1/2,1/2)*ROTATE(PI*2/3)*SHIFT(1,0) ! 右
ELSE
DRAW Set01
END IF
END PICTURE
!------ ミラー縮小4分岐(中)を外すと、シルピンスキーのガスケットもどきになる。
PICTURE D42(k)
IF 0<k THEN
DRAW D42(k-1) WITH SCALE(1/2,1/2)*SHIFT(1/4,SQR(3)/4) ! 上
! これを外す DRAW D42(k-1) WITH SCALE(1/2,-1/2)*SHIFT(1/4,SQR(3)/4) ! 中
DRAW D42(k-1) WITH SCALE(1/2,1/2)*ROTATE(-PI*2/3)*SHIFT(1/4,SQR(3)/4) ! 左
DRAW D42(k-1) WITH SCALE(1/2,1/2)*ROTATE(PI*2/3)*SHIFT(1,0) ! 右
ELSE
DRAW Set01
END IF
END PICTURE
!------ シルピンスキーのガスケット
PICTURE D3(k)
IF 0<k THEN
!---リンク・BASICで描く自己相似図形から拝借
DRAW D3(k-1) WITH SCALE(1/2)
DRAW D3(k-1) WITH SHIFT(-2,0)*SCALE(1/2)*SHIFT(2,0)
DRAW D3(k-1) WITH SHIFT(-1,-SQR(3))*SCALE(1/2)*SHIFT(1,SQR(3))
ELSE
DRAW Set01
END IF
END PICTURE
!------ 親集合の三角図1枚
PICTURE Set01
PLOT LINES: 0,0; 1,0 ;0.5,SQR(3)/2 ;0,0
SET AREA COLOR 2
DRAW disk WITH SCALE(0.1)*SHIFT(px(s),py(s)) ! 飾り1
SET AREA COLOR 3
DRAW disk WITH SCALE(0.1)*SHIFT(px(s+1),py(s+1)) ! 飾り2
SET AREA COLOR 4
DRAW disk WITH SCALE(0.1)*SHIFT(px(s+2),py(s+2)) ! 飾り3
END PICTURE
LET maxim=13 ! 最大枚数 2~1000
DIM buf(1000), bufw(1000)
SUB in_riffle_shuffle !インのリフル。奇数枚は、後半を1枚多め
MAT bufw=buf
FOR i=1 TO n
LET buf(i)= bufw(CEIL(i/2)+MOD(i,2)*INT(n/2)) !1234→3142, 12345→31425
NEXT i
END SUB
SUB out_riffle_shuffle !アウトのリフル。奇数枚は、前半を1枚多め
MAT bufw=buf
FOR i=1 TO n
LET buf(i)= bufw(CEIL(i/2)+MOD(i+1,2)*CEIL(n/2)) !1234→1324, 12345→13243
NEXT i
END SUB
FOR n=2 TO maxim !STEP 2 ! Step を外せば奇数も計算。
!-----
MAT buf=ZER(n) ! 配列サイズ調整、追加
!-----
FOR i=1 TO n
LET buf(i)= i
NEXT i
LET cc=0
LET c=0
!-----
IF maxim<15 THEN MAT PRINT USING REPEAT$(" ###",n) :buf ! 表示、追加
!-----
DO
LET c=c+1
CALL in_riffle_shuffle ! 1234→3142, 12345→31425
!CALL out_riffle_shuffle ! 1234→1324, 12345→13243
!-----
IF maxim<15 THEN MAT PRINT USING REPEAT$(" ###",n) :buf ! 表示、追加
!-----
FOR i=1 TO n
IF buf(i)<> n+1-i THEN EXIT FOR
NEXT i
IF i>n AND cc=0 THEN LET cc=c
FOR i=1 TO n
IF buf(i)<>i THEN EXIT FOR
NEXT i
LOOP UNTIL i>n
PRINT USING "枚数=### 同順=### 逆順=###(復元回数)": n, c, cc
IF maxim<15 THEN PRINT ! 表示、追加
NEXT n
!真理値表
LET a=3 !0011のパターン
LET b=5 !0101のパターン
PRINT " b NOT" !否定
FOR i=0 TO 1
PRINT bit(i,b); 1-bit(i,b) !b'=1-b
NEXT i
PRINT " a b IMP" !論理包含
FOR i=0 TO 3
PRINT bit(i,a); bit(i,b); bit(i,bitor(bitreverse(i,a),b)) !a' or b
NEXT i
PRINT " a b EQV" !同値
FOR i=0 TO 3
PRINT bit(i,a); bit(i,b); 1-bit(i,bitxor(a,b)) !(a xor b)'
NEXT i
!2の補数:定義より
LET n=16 !nビット符号付整数 -2^(n-1)〜2^(n-1)-1
LET m=2^n
LET a=3
LET aa=m-a !a+a'=m
FOR i=N-1 TO 0 STEP -1 !上の位から
PRINT bit(i,aa);
NEXT i
PRINT
!2の補数:反転して1をたす
LET a=3
FOR i=N-1 TO 0 STEP -1 !上の位から
LET a=bitreverse(i,a)
NEXT i
LET a=a+1
PRINT a !nビット符号なし整数 0〜2^n-1
!2の補数:反転して1をたす ※別解
LET a=3
FOR i=0 TO N-1 !下の位から
IF bit(i,a)=1 THEN EXIT FOR !1が見つかるまで
LET a=bitreset(i,a) !0にする
NEXT i
FOR k=i+1 TO N-1 !続き
LET a=bitreverse(k,a) !0を1にする
NEXT k
PRINT a
!加算 a+b
LET a=123
LET b=45
DO WHILE bitand(a,b)>0
LET t=bitxor(a,b)
LET b=sft(bitand(a,b),1)
LET a=t
LOOP
PRINT bitxor(a,b)
END
!ビット演算関連 ※UBASICより
EXTERNAL FUNCTION bit(n,x) !n番目のビット値 ※n,xは整数
IF n<>INT(n) OR x<>INT(x) THEN !整数以外なら
PRINT "パラメータが不適当です。"
STOP
ELSE
LET bit=MOD(INT(x/2^n),2)
END IF
END FUNCTION
EXTERNAL FUNCTION bitset(n,x) !n番目のビットを1にする ※n,xは非負整数
IF n<0 OR n<>INT(n) OR x<0 OR x<>INT(x) THEN !非負整数以外なら
PRINT "パラメータが不適当です。"
STOP
ELSE
LET d=2^n !n桁
LET bitset=(INT(x/d/2)*2+1)*d+MOD(x,d) !大きい桁+1+小さい桁
END IF
END FUNCTION
EXTERNAL FUNCTION bitreset(n,x) !n番目のビットを0にする ※n,xは非負整数
IF n<0 OR n<>INT(n) OR x<0 OR x<>INT(x) THEN !非負整数以外なら
PRINT "パラメータが不適当です。"
STOP
ELSE
LET d=2^n !n桁
LET bitreset=INT(x/d/2)*2*d+MOD(x,d) !大きい桁+1+小さい桁
END IF
END FUNCTION
EXTERNAL FUNCTION bitreverse(n,x) !n番目のビットを反転する ※n,xは非負整数
IF n<0 OR n<>INT(n) OR x<0 OR x<>INT(x) THEN !非負整数以外なら
PRINT "パラメータが不適当です。"
STOP
ELSE
LET d=2^n !n桁
LET a=INT(x/d)
LET bitreverse=(INT(a/2)*4-a+1)*d+MOD(x,d) !大きい桁+NOT+小さい桁
END IF
END FUNCTION
EXTERNAL FUNCTION bitand(a,b) !ビットごとの論理積 ※a,bは非負整数
IF a<0 OR a<>INT(a) OR b<0 OR b<>INT(b) THEN !非負整数以外なら
PRINT "パラメータが不適当です。"
STOP
ELSE
LET c=0 !値
LET d=1
DO UNTIL a=0 OR b=0 !最下位の桁から、桁数が小さい方まで
LET aa=INT(a/2)
LET bb=INT(b/2)
LET c=c + MIN((a-aa*2),(b-bb*2)) * d !and(x,y)=MIN(x,y)
LET a=aa !次へ
LET b=bb
LET d=d*2
LOOP
LET bitand=c
END IF
END FUNCTION
EXTERNAL FUNCTION bitor(a,b) !ビットごとの論理和 ※a,bは非負整数
IF a<0 OR a<>INT(a) OR b<0 OR b<>INT(b) THEN !非負整数以外なら
PRINT "パラメータが不適当です。"
STOP
ELSE
LET c=0
LET d=1
DO UNTIL a=0 AND b=0 !桁数が大きい方
LET aa=INT(a/2)
LET bb=INT(b/2)
LET c=c+MAX((a-aa*2),(b-bb*2)) * d !or(x,y)=MAX(x,y)
LET a=aa !次へ
LET b=bb
LET d=d*2
LOOP
LET bitor=c
END IF
END FUNCTION
EXTERNAL FUNCTION bitxor(a,b) !ビットごとの排他的論理和 ※a,bは非負整数
IF a<0 OR a<>INT(a) OR b<0 OR b<>INT(b) THEN !非負整数以外なら
PRINT "パラメータが不適当です。"
STOP
ELSE
LET c=0
LET d=1
DO UNTIL a=0 AND b=0 !桁数が大きい方
LET aa=INT(a/2)
LET bb=INT(b/2)
LET c=c + MOD((a-aa*2)+(b-bb*2),2) * d !xor(x,y)=MOD(x+y,2)
LET a=aa !次へ
LET b=bb
LET d=d*2
LOOP
LET bitxor=c
END IF
END FUNCTION
EXTERNAL FUNCTION bitcount(x) !1であるビットの個数 ※xは非負整数
IF x<0 OR x<>INT(x) THEN !非負整数以外なら
PRINT "パラメータが不適当です。"
STOP
ELSE
LET c=0 !値
DO UNTIL x=0 !最下位の桁から
LET xx=INT(x/2) !商
LET c=c + (x-xx*2) !余り
LET x=xx !次へ
LOOP
LET bitcount=c
END IF
END FUNCTION
EXTERNAL FUNCTION sft(x,n) !nビットのシフトする ※nは整数
IF n<>INT(n) THEN !整数以外なら
PRINT "パラメータが不適当です。"
STOP
ELSE
IF n<0 THEN LET d=1/2 ELSE LET d=2
FOR i=1 TO ABS(n)
LET x=x*d
NEXT i
LET sft=x
END IF
END FUNCTION
OPTION BASE 0
PUBLIC NUMERIC MAXLEVEL
LET MAXLEVEL=10 !'次数
DIM X(1),Y(MAXLEVEL),L(MAXLEVEL)
LET DISPMODE=0 !' 0 or else
LET INTEGRAL=1 !' INTEGRAL >= 1
LET SWITCH=0 !' 0...閉じた公式 else...開いた公式
IF DISPMODE<>0 THEN
IF INTEGRAL > 1 THEN
PRINT "DIM A(";STR$(INTEGRAL);"),B(";STR$(INTEGRAL);"),N(";STR$(INTEGRAL);")"
PRINT "FOR I=1 TO";INTEGRAL
LET A$="(" & CHR$(34) & "
& STR$(I) & " & CHR$(34) & ")=" & CHR$(34) & ":"
LET B$="(I)"
ELSE
LET A$="=" & CHR$(34) & ":"
LET B$=""
END IF
LET C$="! INPUT PROMPT " & CHR$(34)
PRINT C$;"下限 ";A$;"A";B$
PRINT C$;"上限 ";A$;"B";B$
PRINT C$;"分割数";A$;"N";B$
PRINT "READ A";B$;",B";B$;",N";B$
IF INTEGRAL > 1 THEN PRINT "NEXT"
FOR I=1 TO INTEGRAL
PRINT "DATA 0,1,10"
NEXT I
FOR I=2 TO MAXLEVEL
PRINT "PRINT INTEGRAL";STR$(I);"(";
IF INTEGRAL=1 THEN
PRINT "A,B,N)"
ELSE
FOR J=1 TO INTEGRAL
PRINT "A(";STR$(J);"),B(";STR$(J);"),";
NEXT J
FOR J=1 TO INTEGRAL
PRINT "N(";STR$(J);")";
IF J < INTEGRAL THEN PRINT ",";
NEXT J
PRINT ")"
END IF
NEXT I
PRINT "END"
PRINT
PRINT "EXTERNAL FUNCTION FUNC(";
FOR I=1 TO INTEGRAL
PRINT "X";STR$(I);
IF I < INTEGRAL THEN PRINT ",";
NEXT I
PRINT ")"
PRINT "LET S=1";
FOR I=1 TO INTEGRAL
PRINT "-X";STR$(I);"*X";STR$(I);
NEXT I
PRINT
PRINT "IF S > 0 THEN"
PRINT "LET FUNC=SQR(S)"
PRINT "ELSE"
PRINT "LET FUNC=0"
PRINT "END IF"
PRINT "END FUNCTION"
PRINT
END IF
LET X(1)=1
FOR N=1 TO MAXLEVEL-1
FOR I=0 TO N
CALL CLR(Y)
LET P=1
LET Y(0)=1
FOR J=0 TO N
IF I<>J THEN
LET X(0)=-J
CALL MUL(Y,X)
LET P=P*(I-J)
END IF
NEXT J
CALL INTEGRAL(Y)
IF SWITCH=0 THEN
LET L(I)=HORNER(Y,N)/P
ELSE
LET L(I)=(HORNER(Y,N+1)-HORNER(Y,-1))/P
END IF
NEXT I
IF DISPMODE<>0 THEN
PRINT "EXTERNAL FUNCTION INTEGRAL";STR$(N+1);"(";
IF INTEGRAL > 1 THEN
FOR J=1 TO INTEGRAL
PRINT "A";STR$(J);",B";STR$(J);",";
NEXT J
FOR J=1 TO INTEGRAL
PRINT "N";STR$(J);
IF J < INTEGRAL THEN PRINT ",";
NEXT J
ELSE
PRINT "A,B,N";
END IF
PRINT ")"
IF SWITCH=0 THEN LET A$=STR$(N) ELSE LET A$=STR$(N+2)
IF INTEGRAL=1 THEN
PRINT "LET H=(B-A)/N/";A$
PRINT "LET S=0"
PRINT "FOR K=0 TO N-1"
PRINT "LET S=S";
FOR I=0 TO N
IF SWITCH=0 THEN LET B$=STR$(I) ELSE LET B$=STR$(I+1)
IF L(I) < 0 THEN PRINT "-"; ELSE PRINT "+";
PRINT STR$(ABS(L(I)));"*H*FUNC(A+H*(";A$;"*K+";B$;"))";
NEXT I
PRINT
PRINT "NEXT"
ELSE
IF SWITCH=0 THEN
PRINT "DIM R(0 TO ";STR$(N);")"
ELSE
PRINT "DIM R(";STR$(N+1);")"
END IF
FOR I=0 TO N
IF SWITCH=0 THEN LET B$=STR$(I) ELSE LET B$=STR$(I+1)
PRINT "R(";B$;")=";
IF L(I) < 0 THEN PRINT "-";
PRINT STR$(ABS(L(I)))
NEXT I
FOR J=1 TO INTEGRAL
PRINT
"LET H";STR$(J);"=(B";STR$(J);"-A";STR$(J);")/N";STR$(J);"/";A$
NEXT J
PRINT "LET S=0"
FOR J=INTEGRAL TO 1 STEP -1
PRINT "FOR K";STR$(J);"=0 TO N";STR$(J);"-1"
NEXT J
FOR J=1 TO INTEGRAL
IF SWITCH=0 THEN
PRINT "FOR J";STR$(J);"=0 TO";N
ELSE
PRINT "FOR J";STR$(J);"=1 TO";N+1
END IF
NEXT J
PRINT "LET S=S+";
FOR J=1 TO INTEGRAL
PRINT "R(J";STR$(J);")*";
NEXT J
FOR I=1 TO INTEGRAL
PRINT "H";STR$(I);"*";
NEXT I
PRINT "FUNC(";
FOR I=1 TO INTEGRAL
PRINT
"A";STR$(I);"+H";STR$(I);"*(";A$;"*K";STR$(I);"+J";STR$(I);")";
IF I < INTEGRAL THEN PRINT ",";
NEXT I
PRINT ")"
FOR I=1 TO INTEGRAL*2
PRINT "NEXT"
NEXT I
END IF
PRINT "LET INTEGRAL";STR$(N+1);"=S"
PRINT "END FUNCTION"
ELSE
PRINT "∫(x";STR$(N);",x0)f(x)dx=";
FOR I=0 TO N
IF L(I) < 0 THEN
PRINT "-";
ELSE
IF I > 0 THEN PRINT "+";
END IF
PRINT STR$(ABS(L(I)));"*h*f(x";STR$(I);")";
NEXT I
PRINT
END IF
PRINT
NEXT N
END
EXTERNAL SUB MUL(A(),B())
OPTION BASE 0
DIM C(MAXLEVEL)
FOR I=0 TO MAXLEVEL-1
FOR J=0 TO 1
LET C(I+J)=C(I+J)+A(I)*B(J)
NEXT J
NEXT I
CALL COPY(A,C)
END SUB
EXTERNAL FUNCTION HORNER(A(),XX)
FOR N=MAXLEVEL TO 0 STEP -1
IF A(N)<>0 THEN EXIT FOR
NEXT N
LET Y=A(N)
FOR I=N-1 TO 0 STEP -1
LET Y=Y*XX+A(I)
NEXT I
LET HORNER=Y
END FUNCTION
EXTERNAL SUB COPY(X(),Y())
FOR I=0 TO MAXLEVEL
LET X(I)=Y(I)
NEXT I
END SUB
EXTERNAL SUB CLR(X())
FOR I=0 TO MAXLEVEL
LET X(I)=0
NEXT I
END SUB
EXTERNAL SUB INTEGRAL(A())
OPTION BASE 0
DIM B(MAXLEVEL)
FOR I=MAXLEVEL-1 TO 0 STEP -1
LET B(I+1)=A(I)/(I+1)
NEXT I
CALL COPY(A,B)
END SUB
OPTION BASE 0
OPTION ARITHMETIC DECIMAL_HIGH
PUBLIC NUMERIC MAXLEVEL,EPS
LET MAXLEVEL=10 !'次数
DIM X(MAXLEVEL),W(MAXLEVEL)
LET KETA=16 !'求める桁数
LET EPS=10^(-KETA)
LET DISPMODE=0 !' 0 or else
LET INTEGRAL=1 !' INTEGRAL >= 1
IF DISPMODE<>0 THEN
CALL LEGENDREPARA(MAXLEVEL,X,W)
PRINT "DIM X(";STR$(MAXLEVEL);"),W(";STR$(MAXLEVEL);")"
FOR I=1 TO INTEGRAL
PRINT "! INPUT PROMPT ";CHR$(34);"下限 ";STR$(I);"=";CHR$(34);":A";STR$(I)
PRINT "! INPUT PROMPT ";CHR$(34);"上限 ";STR$(I);"=";CHR$(34);":B";STR$(I)
NEXT I
FOR I=1 TO INTEGRAL
PRINT "LET A";STR$(I);"=0"
PRINT "LET B";STR$(I);"=1"
NEXT I
FOR J=1 TO INTEGRAL
PRINT "LET U";STR$(J);"=(B";STR$(J);"+A";STR$(J);")/2"
PRINT "LET V";STR$(J);"=(B";STR$(J);"-A";STR$(J);")/2"
NEXT J
PRINT "FOR I=1 TO";MAXLEVEL
PRINT "READ X(I),W(I)"
PRINT "NEXT"
PRINT "LET S=0"
FOR J=1 TO INTEGRAL
PRINT "FOR K";STR$(J);"=1 TO";MAXLEVEL
NEXT J
PRINT "LET S=S+";
FOR J=1 TO INTEGRAL
PRINT "W(K";STR$(J);")*";
NEXT J
PRINT "FUNC(";
FOR I=1 TO INTEGRAL
PRINT "U";STR$(I);"+V";STR$(I);"*X(K";STR$(I);")";
IF I < INTEGRAL THEN PRINT ",";
NEXT I
PRINT ")";
FOR J=1 TO INTEGRAL
PRINT "*V";STR$(J);
NEXT J
PRINT
FOR J=1 TO INTEGRAL
PRINT "NEXT"
NEXT J
PRINT "PRINT S"
FOR I=1 TO MAXLEVEL
PRINT "DATA ";
PRINT USING "#." & REPEAT$("#",KETA):X(I);
PRINT ",";
PRINT USING "#." & REPEAT$("#",KETA) & "^^^^":W(I)
NEXT I
PRINT "END"
PRINT
PRINT "EXTERNAL FUNCTION FUNC(";
FOR I=1 TO INTEGRAL
PRINT "X";STR$(I);
IF I < INTEGRAL THEN PRINT ",";
NEXT I
PRINT ")"
PRINT "LET S=1";
FOR I=1 TO INTEGRAL
PRINT "-X";STR$(I);"*X";STR$(I);
NEXT I
PRINT
PRINT "IF S > 0 THEN"
PRINT "LET FUNC=SQR(S)"
PRINT "ELSE"
PRINT "LET FUNC=0"
PRINT "END IF"
PRINT "END FUNCTION"
ELSE
FOR N=2 TO MAXLEVEL
PRINT TAB(8+KETA/2);"分点";TAB(8+KETA*1.5);" 重み"
CALL LEGENDREPARA(N,X,W)
FOR I=1 TO N
PRINT "No.";I;":";
PRINT USING "#." & REPEAT$("#",KETA):X(I);
PRINT " ";
PRINT USING "#." & REPEAT$("#",KETA) & "^^^^":W(I)
NEXT I
NEXT N
END IF
END
EXTERNAL SUB LEGENDREPARA(N,A(),W())
OPTION ARITHMETIC DECIMAL_HIGH
OPTION BASE 0
DIM P(MAXLEVEL),D(MAXLEVEL)
CALL LEGENDREPOLY(N,P)
FOR I=0 TO N
LET P(I)=P(I)/P(N)
NEXT I
FOR I=1 TO N
CALL DERIVATIVE(P,D) !'微分
LET XX=-1 !'初期値
DO
LET X=XX
LET XX=X-HORNER(N,P,X)/HORNER(N,D,X) !'ニュートン法
LOOP UNTIL ABS(HORNER(N,P,XX)) < EPS AND ABS(X-XX) < EPS
LET A(I)=XX !'分点
LET W(I)=WEIGHT(N,XX) !'重み
CALL DIV(P,XX) !'組立除法
NEXT I
END SUB
EXTERNAL SUB LEGENDREPOLY(KK,NEWP()) !'ルジャンドル多項式(係数)
OPTION ARITHMETIC DECIMAL_HIGH
OPTION BASE 0
DIM P(KK+1),OLDP(KK),PP(KK)
LET OLDP(0)=1
LET P(1)=1
FOR I=0 TO KK
LET NEWP(I)=0
NEXT I
FOR K=2 TO KK
FOR J=1 TO K
LET NEWP(J)=NEWP(J)+(2*K-1)/K*P(J-1)
LET NEWP(J-1)=NEWP(J-1)-(K-1)/K*OLDP(J-1)
NEXT J
IF K < KK THEN
FOR I=0 TO K
LET OLDP(I)=P(I)
LET P(I)=NEWP(I)
LET NEWP(I)=0
NEXT I
END IF
NEXT K
END SUB
EXTERNAL FUNCTION LEGENDRE(K,X) !'ルジャンドル多項式(値)
OPTION ARITHMETIC DECIMAL_HIGH
OPTION BASE 0
DIM PP(K+1)
LET PP(0)=1
LET PP(1)=X
FOR N=1 TO K-1
LET PP(N+1)=((2*N+1)*X*PP(N)-N*PP(N-1))/(N+1)
NEXT N
LET LEGENDRE=PP(K)
END FUNCTION
EXTERNAL FUNCTION WEIGHT(N,X) !'重み
OPTION ARITHMETIC DECIMAL_HIGH
LET WEIGHT=2*(1-X^2)/(N*LEGENDRE(N-1,X))^2
END FUNCTION
EXTERNAL FUNCTION HORNER(N,A(),X)
OPTION ARITHMETIC DECIMAL_HIGH
LET Y=A(N)
FOR I=N-1 TO 0 STEP -1
LET Y=Y*X+A(I)
NEXT I
LET HORNER=Y
END FUNCTION
EXTERNAL SUB DERIVATIVE(A(),B()) !'微分
OPTION ARITHMETIC DECIMAL_HIGH
FOR I=MAXLEVEL TO 1 STEP -1
LET B(I-1)=I*A(I)
NEXT I
LET B(MAXLEVEL)=0
END SUB
EXTERNAL SUB DIV(A(),P) !'組立除法
!'A(N)*X^N+A(N-1)*X^(N-1)+...+A(2)*X^2+A(1)*X+A(0)=(X-P)(C(N-1)*X^(N-1)+...+C(2)*X^2+C(1)*X+C(0))
OPTION BASE 0
OPTION ARITHMETIC DECIMAL_HIGH
DIM C(MAXLEVEL)
FOR I=MAXLEVEL TO 1 STEP -1
LET C(I-1)=A(I)+C(I)*P
NEXT I
CALL COPY(A,C)
END SUB
EXTERNAL SUB COPY(X(),Y())
OPTION ARITHMETIC DECIMAL_HIGH
FOR I=0 TO MAXLEVEL
LET X(I)=Y(I)
NEXT I
END SUB
---------------------------------------------------
ルジャンドル多項式表示
有理数モードでお試しください
OPTION BASE 0
PUBLIC NUMERIC MAXLEVEL
LET MAXLEVEL=20 !'次数
DIM P(MAXLEVEL)
PRINT "P(0)=1"
PRINT "P(1)=X"
FOR K=2 TO MAXLEVEL
CALL LEGENDREPOLY(K,P) !'上記参照(OPTION ARITHMETIC DECIMAL_HIGHを外す)
PRINT "P(";STR$(K);")=";
CALL DISPLAY(P)
NEXT K
END
EXTERNAL SUB DISPLAY(A())
FOR N=MAXLEVEL TO 0 STEP -1
IF A(N)<>0 THEN EXIT FOR
NEXT N
IF N > 1 THEN
IF A(N) < 0 THEN PRINT "-";
IF ABS(A(N))<>1 THEN
PRINT STR$(ABS(A(N)));"*X^";STR$(N);
ELSE
PRINT "X^";STR$(N);
END IF
END IF
FOR I=N-1 TO 2 STEP -1
IF A(I)<>0 THEN
IF A(I) < 0 THEN PRINT "-"; ELSE PRINT "+";
IF ABS(A(I))<>1 THEN
PRINT STR$(ABS(A(I)));"*X^";STR$(I);
ELSEIF ABS(A(I))=1 THEN
PRINT "X^";STR$(I);
END IF
END IF
NEXT I
IF A(1)<>0 THEN
IF N > 1 THEN
IF A(1) < 0 THEN PRINT "-"; ELSE PRINT "+";
END IF
IF ABS(A(1))<>1 THEN
PRINT STR$(ABS(A(1)));"*X";
ELSEIF ABS(A(1))=1 THEN
PRINT "X";
END IF
END IF
IF A(0)<>0 THEN
IF A(0) < 0 THEN PRINT "-"; ELSE PRINT "+";
PRINT STR$(ABS(A(0)));
END IF
PRINT
END SUB
OPTION BASE 0
OPTION ARITHMETIC DECIMAL_HIGH
PUBLIC NUMERIC MAXLEVEL,EPS
LET MAXLEVEL=10
DIM X(MAXLEVEL),W(MAXLEVEL)
LET KETA=16
LET EPS=10^(-KETA)
LET DISPMODE=0 !' 0 or else
LET INTEGRAL=1 !' INTEGRAL >= 1
IF DISPMODE<>0 THEN
CALL LAGUERREPARA(MAXLEVEL,X,W)
PRINT "DIM X(";STR$(MAXLEVEL);"),W(";STR$(MAXLEVEL);")"
PRINT "FOR I=1 TO";MAXLEVEL
PRINT "READ X(I),W(I)"
PRINT "NEXT"
FOR I=1 TO INTEGRAL
PRINT "INPUT PROMPT ";CHR$(34);"GAMMA(";
FOR J=1 TO INTEGRAL
PRINT "X";STR$(J);
IF J < INTEGRAL THEN PRINT ",";
NEXT J
PRINT ") X";STR$(I);"=";CHR$(34);":U";STR$(I)
NEXT I
PRINT "LET S=0"
FOR I=1 TO INTEGRAL
PRINT "FOR I";STR$(I);"=1 TO";MAXLEVEL
NEXT I
PRINT "LET S=S+";
FOR I=1 TO INTEGRAL
PRINT "W(I";STR$(I);")*";
NEXT I
PRINT "FUNC(";
FOR I=1 TO INTEGRAL
PRINT "X(I";STR$(I);"),";
NEXT I
FOR I=1 TO INTEGRAL
PRINT "U";STR$(I);
IF I < INTEGRAL THEN PRINT ",";
NEXT I
PRINT ")*EXP(";
FOR I=1 TO INTEGRAL
PRINT "X(I";STR$(I);")";
IF I < INTEGRAL THEN PRINT "+";
NEXT I
PRINT ")"
FOR I=1 TO INTEGRAL
PRINT "NEXT"
NEXT I
PRINT "PRINT S"
FOR I=1 TO MAXLEVEL
PRINT "DATA ";
PRINT USING "##." & REPEAT$("#",KETA):X(I);
PRINT ",";
PRINT USING "#." & REPEAT$("#",KETA) & "^^^^":W(I)
NEXT I
PRINT "END"
PRINT
PRINT "EXTERNAL FUNCTION FUNC(";
FOR I=1 TO INTEGRAL
PRINT "X";STR$(I);",";
NEXT I
FOR I=1 TO INTEGRAL
PRINT "U";STR$(I);
IF I < INTEGRAL THEN PRINT ",";
NEXT I
PRINT ")"
PRINT "FUNC=";
FOR I=1 TO INTEGRAL
PRINT "EXP(-X";STR$(I);")*X";STR$(I);"^(U";STR$(I);"-1)";
IF I < INTEGRAL THEN PRINT "*";
NEXT I
PRINT
PRINT "END FUNCTION"
ELSE
FOR N=2 TO MAXLEVEL
CALL LAGUERREPARA(N,X,W)
PRINT TAB(8+KETA/2);"分点";TAB(8+KETA*1.5);" 重み"
FOR I=1 TO N
PRINT "No.";I;":";
PRINT USING "##." & REPEAT$("#",KETA):X(I);
PRINT " ";
PRINT USING "#." & REPEAT$("#",KETA) & "^^^^":W(I)
NEXT I
NEXT N
END IF
END
EXTERNAL SUB LAGUERREPARA(N,A(),W())
OPTION ARITHMETIC DECIMAL_HIGH
OPTION BASE 0
DIM LA(MAXLEVEL+1),D(MAXLEVEL)
CALL LAGUERREPOLY(N,LA)
FOR I=0 TO N
LET LA(I)=LA(I)/LA(N)
NEXT I
FOR I=1 TO N
CALL DERIVATIVE(LA,D)
LET XX=0
DO
LET X=XX
LET XX=X-HORNER(N,LA,X)/HORNER(N,D,X)
LOOP UNTIL ABS(HORNER(N,LA,XX)) < EPS AND ABS(X-XX) < EPS
LET A(I)=XX
LET W(I)=WEIGHT(N,XX)
CALL DIV(LA,XX)
NEXT I
END SUB
EXTERNAL SUB LAGUERREPOLY(N,NEWP()) !'ラゲール多項式(係数)
OPTION ARITHMETIC DECIMAL_HIGH
OPTION BASE 0
DIM P(N+1),OLDP(N)
LET OLDP(0)=1
LET P(1)=-1
LET P(0)=1
FOR I=0 TO N
LET NEWP(I)=0
NEXT I
FOR K=2 TO N
FOR J=0 TO K
LET NEWP(J)=NEWP(J)+(2*K-1)*P(J)-(K-1)^2*OLDP(J)
LET NEWP(J+1)=NEWP(J+1)-P(J)
NEXT J
IF K < N THEN
FOR I=0 TO K
LET OLDP(I)=P(I)
LET P(I)=NEWP(I)
LET NEWP(I)=0
NEXT I
END IF
NEXT K
END SUB
EXTERNAL FUNCTION LAGUERRE(NN,X) !'ラゲール多項式(値)
OPTION ARITHMETIC DECIMAL_HIGH
OPTION BASE 0
DIM L(NN+1)
LET L(0)=1
LET L(1)=1-X
FOR N=1 TO NN-1
LET L(N+1)=(2*N+1-X)*L(N)-N*N*L(N-1)
NEXT N
LET LAGUERRE=L(NN)
END FUNCTION
EXTERNAL FUNCTION WEIGHT(N,X)
OPTION ARITHMETIC DECIMAL_HIGH
LET WEIGHT=FAC(N)^2/(X*LAGUERREDIFF(N,X)^2)
END FUNCTION
EXTERNAL FUNCTION LAGUERREDIFF(N,X)
OPTION ARITHMETIC DECIMAL_HIGH
LET LAGUERREDIFF=(LAGUERRE(N+1,X)-(N+1-X)*LAGUERRE(N,X))/X
END FUNCTION
EXTERNAL FUNCTION FAC(X)
OPTION ARITHMETIC DECIMAL_HIGH
LET S=1
FOR I=2 TO X
LET S=S*I
NEXT I
LET FAC=S
END FUNCTION
EXTERNAL SUB DERIVATIVE(A(),B())
OPTION ARITHMETIC DECIMAL_HIGH
FOR I=MAXLEVEL TO 1 STEP -1
LET B(I-1)=I*A(I)
NEXT I
LET B(MAXLEVEL)=0
END SUB
EXTERNAL FUNCTION HORNER(N,A(),X)
OPTION ARITHMETIC DECIMAL_HIGH
LET Y=A(N)
FOR I=N-1 TO 0 STEP -1
LET Y=Y*X+A(I)
NEXT I
LET HORNER=Y
END FUNCTION
EXTERNAL SUB DIV(A(),P)
OPTION BASE 0
OPTION ARITHMETIC DECIMAL_HIGH
DIM C(MAXLEVEL)
FOR I=MAXLEVEL TO 1 STEP -1
LET C(I-1)=A(I)+C(I)*P
NEXT I
CALL COPY(A,C)
END SUB
EXTERNAL SUB COPY(X(),Y())
OPTION ARITHMETIC DECIMAL_HIGH
FOR I=0 TO MAXLEVEL
LET X(I)=Y(I)
NEXT I
END SUB
OPTION BASE 0
OPTION ARITHMETIC DECIMAL_HIGH
PUBLIC NUMERIC MAXLEVEL,EPS
LET MAXLEVEL=10
DIM X(MAXLEVEL),W(MAXLEVEL)
LET KETA=16
LET EPS=10^(-KETA)
LET DISPMODE=0 !' 0 or else
LET INTEGRAL=1 !' INTEGRAL >= 1
IF DISPMODE<>0 THEN
CALL HERMITEPARA(MAXLEVEL,X,W)
PRINT "DIM X(";STR$(MAXLEVEL);"),W(";STR$(MAXLEVEL);")"
PRINT "FOR I=1 TO";MAXLEVEL
PRINT "READ X(I),W(I)"
PRINT "NEXT"
PRINT "LET S=0"
FOR I=1 TO INTEGRAL
PRINT "FOR I";STR$(I);"=1 TO";MAXLEVEL
NEXT I
PRINT "LET S=S+";
FOR I=1 TO INTEGRAL
PRINT "W(I";STR$(I);")*";
NEXT I
PRINT "FUNC(";
FOR I=1 TO INTEGRAL
PRINT "X(I";STR$(I);")";
IF I < INTEGRAL THEN PRINT ",";
NEXT I
PRINT ")*EXP(";
FOR I=1 TO INTEGRAL
PRINT "X(I";STR$(I);")^2";
IF I < INTEGRAL THEN PRINT "+";
NEXT I
PRINT ")"
FOR I=1 TO INTEGRAL
PRINT "NEXT"
NEXT I
PRINT "PRINT S,PI^";STR$(INTEGRAL/2)
FOR I=1 TO MAXLEVEL
PRINT "DATA ";
PRINT USING "##." & REPEAT$("#",KETA):X(I);
PRINT ",";
PRINT USING "#." & REPEAT$("#",KETA) & "^^^^":W(I)
NEXT I
PRINT "END"
PRINT
PRINT "EXTERNAL FUNCTION FUNC(";
FOR I=1 TO INTEGRAL
PRINT "X";STR$(I);
IF I < INTEGRAL THEN PRINT ",";
NEXT I
PRINT ")"
PRINT "LET FUNC=EXP(";
FOR I=1 TO INTEGRAL
PRINT "-X";STR$(I);"^2";
NEXT I
PRINT ")"
PRINT "END FUNCTION"
ELSE
FOR N=2 TO MAXLEVEL
CALL HERMITEPARA(N,X,W)
PRINT TAB(8+KETA/2);"分点";TAB(8+KETA*1.5);" 重み"
FOR I=1 TO N
PRINT "No.";I;":";
PRINT USING "##." & REPEAT$("#",KETA):X(I);
PRINT " ";
PRINT USING "#." & REPEAT$("#",KETA) & "^^^^":W(I)
NEXT I
NEXT N
END IF
END
EXTERNAL SUB HERMITEPARA(N,A(),W())
OPTION ARITHMETIC DECIMAL_HIGH
OPTION BASE 0
DIM H(MAXLEVEL),D(MAXLEVEL)
CALL HERMITEPOLY(N,H)
FOR I=0 TO N
LET H(I)=H(I)/H(N)
NEXT I
FOR I=1 TO N
CALL DERIVATIVE(H,D)
LET XX=-15
DO
LET X=XX
LET XX=X-HORNER(N,H,X)/HORNER(N,D,X)
LOOP UNTIL ABS(HORNER(N,H,XX)) < EPS AND ABS(X-XX) < EPS
LET A(I)=XX
LET W(I)=WEIGHT(N,XX)
CALL DIV(H,XX)
NEXT I
END SUB
EXTERNAL SUB HERMITEPOLY(N,NEWP()) !'エルミート多項式(係数)
OPTION ARITHMETIC DECIMAL_HIGH
OPTION BASE 0
DIM P(N+1),OLDP(N)
LET OLDP(0)=1
LET P(1)=2
FOR I=0 TO N
LET NEWP(I)=0
NEXT I
FOR K=2 TO N
FOR J=1 TO K
LET NEWP(J)=NEWP(J)+2*P(J-1)
LET NEWP(J-1)=NEWP(J-1)-2*(K-1)*OLDP(J-1)
NEXT J
IF K < N THEN
FOR I=0 TO K
LET OLDP(I)=P(I)
LET P(I)=NEWP(I)
LET NEWP(I)=0
NEXT I
END IF
NEXT K
END SUB
EXTERNAL FUNCTION HERMITE(NN,X) !'エルミート多項式(値)
OPTION ARITHMETIC DECIMAL_HIGH
OPTION BASE 0
DIM H(NN+1)
LET H(0)=1
LET H(1)=2*X
FOR N=1 TO NN-1
LET H(N+1)=2*X*H(N)-2*N*H(N-1)
NEXT N
LET HERMITE=H(NN)
END FUNCTION
EXTERNAL FUNCTION WEIGHT(N,X) !'重み
OPTION ARITHMETIC DECIMAL_HIGH
LET WEIGHT=2^(N+1)*FAC(N)*SQR(PI)/HERMITE(N+1,X)^2
END FUNCTION
EXTERNAL FUNCTION FAC(X)
OPTION ARITHMETIC DECIMAL_HIGH
LET S=1
FOR I=2 TO X
LET S=S*I
NEXT I
LET FAC=S
END FUNCTION
EXTERNAL FUNCTION HORNER(N,A(),X)
OPTION ARITHMETIC DECIMAL_HIGH
LET Y=A(N)
FOR I=N-1 TO 0 STEP -1
LET Y=Y*X+A(I)
NEXT I
LET HORNER=Y
END FUNCTION
EXTERNAL SUB DERIVATIVE(A(),B())
OPTION ARITHMETIC DECIMAL_HIGH
FOR I=MAXLEVEL TO 1 STEP -1
LET B(I-1)=I*A(I)
NEXT I
LET B(MAXLEVEL)=0
END SUB
EXTERNAL SUB DIV(A(),P)
OPTION BASE 0
OPTION ARITHMETIC DECIMAL_HIGH
DIM C(MAXLEVEL)
FOR I=MAXLEVEL TO 1 STEP -1
LET C(I-1)=A(I)+C(I)*P
NEXT I
CALL COPY(A,C)
END SUB
EXTERNAL SUB COPY(X(),Y())
OPTION ARITHMETIC DECIMAL_HIGH
FOR I=0 TO MAXLEVEL
LET X(I)=Y(I)
NEXT I
END SUB
PUBLIC NUMERIC MAXLEVEL
OPTION BASE 0
LET MAXLEVEL=10 !'最大次数 (MAXLEVEL > N)
LET N=5 !'データ数
DIM X(N),Y(N),A(MAXLEVEL),B(MAXLEVEL)
FOR I=1 TO N
READ X(I),Y(I) !'y=x^2
NEXT I
CALL LARGRANGE(N,X,Y,A) !'ラグランジュ多項式
CALL INTEGRAL(A,B) !'積分
PRINT HORNER(N,B,X(N))-HORNER(N,B,X(1));X(N)^3/3-X(1)^3/3
!'CALL DERIVATIVE(A,B) !'微分
!'INPUT PROMPT "f'(x) x=":XX
!'PRINT HORNER(N,B,XX);2*XX
DATA 0,0 !'離散値データ X値は等間隔でなくてもいい
DATA 1,1
DATA 3,9
DATA 4,16
DATA 6,36
END
EXTERNAL SUB LARGRANGE(N,X(),Y(),A())
OPTION BASE 0
DIM U(MAXLEVEL),V(MAXLEVEL)
CALL CLR(A)
LET U(1)=1
FOR I = 1 TO N
LET R = Y(I)
CALL CLR(V)
LET V(0)=1
FOR J = 1 TO N
IF I <> J THEN
LET U(0)=-X(J)
CALL MUL(V,U)
LET R = R / (X(I)-X(J))
END IF
NEXT J
CALL SHORTMUL(V,R)
CALL ADD(A,V)
NEXT I
END SUB
EXTERNAL FUNCTION HORNER(N,A(),XX)
LET Y=A(N)
FOR I=N-1 TO 0 STEP -1
LET Y=Y*XX+A(I)
NEXT I
LET HORNER=Y
END FUNCTION
EXTERNAL SUB MUL(A(),B())
OPTION BASE 0
DIM C(MAXLEVEL)
FOR I=0 TO MAXLEVEL-1
FOR J=0 TO 1
LET C(I+J)=C(I+J)+A(I)*B(J)
NEXT J
NEXT I
CALL COPY(A,C)
END SUB
EXTERNAL SUB INTEGRAL(A(),B())
FOR I=MAXLEVEL-1 TO 0 STEP -1
LET B(I+1)=A(I)/(I+1)
NEXT I
LET B(0)=0
END SUB
EXTERNAL SUB ADD(A(),B())
FOR I=0 TO MAXLEVEL
LET A(I)=A(I)+B(I)
NEXT I
END SUB
EXTERNAL SUB COPY(X(),Y())
FOR I=0 TO MAXLEVEL
LET X(I)=Y(I)
NEXT I
END SUB
EXTERNAL SUB CLR(X())
FOR I=0 TO MAXLEVEL
LET X(I)=0
NEXT I
END SUB
EXTERNAL SUB SHORTMUL(A(),X)
FOR I=0 TO MAXLEVEL
LET A(I)=A(I)*X
NEXT I
END SUB
EXTERNAL SUB DERIVATIVE(A(),B())
FOR I=MAXLEVEL TO 1 STEP -1
LET B(I-1)=I*A(I)
NEXT I
LET B(MAXLEVEL)=0
END SUB
LET N=5 !'データ数 条件...MOD(N-1,M-1)=0
LET M=3 !'小区間 間隔数
DIM X(N),Y(N),XX(M),YY(M)
FOR I=1 TO N
READ X(I),Y(I) !'y=x^2
NEXT I
LET S=0
FOR I=1 TO N-M+1 STEP M-1 !'小区間に分割する X(1)〜X(3),X(3)〜X(5),X(5)〜X(7),...
FOR K=0 TO M-1
LET XX(K+1)=X(I+K)
LET YY(K+1)=Y(I+K)
NEXT K
LET S=S+INTEGRAL(XX,YY,M) !'全区間分を足し合わせる
!'LET SS=SS+INTEGRAL2(XX,YY,M) !'下記参照
NEXT I
PRINT S;(X(N)^3-X(1)^3)/3 !' ;SS
!'INPUT PROMPT "f'(x) x=":XX
!'PRINT DERIVATIVE(N,X,Y,XX);2*XX !'下記参照
DATA 0,0 !'離散値データ X値は等間隔でなくてもいい
DATA 1,1
DATA 3,9
DATA 4,16
DATA 6,36
END
EXTERNAL FUNCTION INTEGRAL(X(),Y(),M)
DECLARE EXTERNAL FUNCTION COMB
DIM H(M),XX(M),TEMP(M)
FOR I=1 TO M
LET H(I)=1
LET K=0
FOR J=1 TO M
IF I<>J THEN
LET H(I)=H(I)/(X(I)-X(J))
LET K=K+1
LET XX(K)=X(J)
END IF
NEXT J
LET SIGN=1
FOR J=M TO 1 STEP -1
LET SM=SM+SIGN*X(M)^J/J*COMB(XX,M,M-J,TEMP,1)*H(I)*Y(I)
LET S1=S1+SIGN*X(1)^J/J*COMB(XX,M,M-J,TEMP,1)*H(I)*Y(I)
LET SIGN=-SIGN
NEXT J
NEXT I
LET INTEGRAL=SM-S1
END FUNCTION
EXTERNAL FUNCTION COMB(X(),N,R,A(),K)
IF R=0 THEN
LET S=1
FOR I=1 TO N
IF A(I)=1 THEN LET S=S*X(I)
NEXT I
LET COMB=S
ELSE
FOR I=K TO N-R+1
LET A(I)=1
LET SS=SS+COMB(X,N,R-1,A,I+1)
LET A(I)=0
NEXT I
LET COMB=SS
END IF
END FUNCTION
EXTERNAL FUNCTION INTEGRAL2(X(),Y(),N)
DIM A(N,N),B(N)
FOR I=1 TO N
FOR J=1 TO N
LET A(I,J)=X(J)^(I-1)
NEXT J
LET B(I)=(X(N)^I-X(1)^I)/I
NEXT I
MAT A=INV(A)
MAT B=A*B
FOR I=1 TO N
LET S=S+B(I)*Y(I)
NEXT I
LET INTEGRAL2=S
END FUNCTION
EXTERNAL FUNCTION DERIVATIVE(N,X(),Y(),XX)
DIM A(N,N),B(N)
FOR I=1 TO N
FOR J=1 TO N
LET A(I,J)=X(J)^I
NEXT J
LET B(I)=I*XX^(I-1)
!'LET B(I)=I*(I-1)*XX^(I-2) !'2階微分
NEXT I
MAT A=INV(A)
MAT B=A*B
FOR I=1 TO N
LET S=S+B(I)*Y(I)
NEXT I
LET DERIVATIVE=S
END FUNCTION
EXTERNAL FUNCTION DIFF(N,X(),Y(),XX)
DIM A(N)
FOR I=1 TO N
LET L=1
LET KK=0
FOR J=1 TO N
IF J<>I THEN
LET KK=KK+1
LET L=L*(X(I)-X(J))
LET A(KK)=X(J)
END IF
NEXT J
LET S1=0
FOR J=1 TO N-1
LET S=1
FOR K=1 TO N-1
IF K<>J THEN LET S=S*(XX-A(K))
NEXT K
LET S1=S1+S
NEXT J
LET SS=SS+S1*Y(I)/L
NEXT I
LET DIFF=SS
END FUNCTION
PUBLIC NUMERIC LEVEL
INPUT PROMPT "多重積分 LEVEL=":LEVEL
DIM A(LEVEL),B(LEVEL),N(LEVEL),AA(LEVEL)
FOR I=1 TO LEVEL
!'INPUT PROMPT "下限 =":A(I)
!'INPUT PROMPT "上限 =":B(I)
!'INPUT PROMPT "分割数=":N(I)
READ A(I),B(I),N(I)
NEXT I
DATA 0,1,10
DATA 0,1,10
DATA 0,1,10
DATA 0,1,10
PRINT SIMPSONRECURSIVE(LEVEL,AA,A,B,N)
END
EXTERNAL FUNCTION SIMPSONRECURSIVE(LEV,AA(),A(),B(),N())
IF LEV=0 THEN
LET SIMPSONRECURSIVE=FUNC(AA)
ELSE
LET H=(B(LEV)-A(LEV))/N(LEV)/2
FOR K=0 TO N(LEV)-1
LET AA(LEV)=A(LEV)+H*K*2
LET S=S+1/3*H*SIMPSONRECURSIVE(LEV-1,AA,A,B,N)
LET AA(LEV)=A(LEV)+H*(2*K+1)
LET S=S+4/3*H*SIMPSONRECURSIVE(LEV-1,AA,A,B,N)
LET AA(LEV)=A(LEV)+H*(2*K+2)
LET S=S+1/3*H*SIMPSONRECURSIVE(LEV-1,AA,A,B,N)
NEXT K
LET SIMPSONRECURSIVE=S
END IF
END FUNCTION
EXTERNAL FUNCTION FUNC(X())
LET S=1
FOR I=1 TO LEVEL
LET S=S-X(I)*X(I)
NEXT I
IF S > 0 THEN
LET FUNC=SQR(S)
ELSE
LET FUNC=0
END IF
END FUNCTION
PUBLIC NUMERIC W(10),X(10),LEVEL
INPUT PROMPT "多重積分 LEVEL=":LEVEL
DIM A(LEVEL),B(LEVEL),XX(LEVEL),WW(LEVEL)
FOR I=1 TO LEVEL
READ A(I),B(I)
NEXT I
DATA 0,1
DATA 0,1
DATA 0,1
DATA 0,1
RESTORE 10
FOR I=1 TO 10
READ X(I),W(I)
NEXT I
PRINT LEGENDRERECURSIVE(LEVEL,XX,WW,A,B,10)
10 DATA -.9739065285171717,6.6671344308688138E-02 !'10点 ルジャンドル則
DATA -.8650633666889845,1.4945134915058059E-01
DATA -.6794095682990244,2.1908636251598204E-01
DATA -.4333953941292472,2.6926671930999636E-01
DATA -.1488743389816312,2.9552422471475287E-01
DATA .1488743389816312,2.9552422471475287E-01
DATA .4333953941292472,2.6926671930999636E-01
DATA .6794095682990244,2.1908636251598204E-01
DATA .8650633666889845,1.4945134915058059E-01
DATA .9739065285171717,6.6671344308688138E-02
END
EXTERNAL FUNCTION LEGENDRERECURSIVE(LEV,XX(),WW(),A(),B(),N)
IF LEV=0 THEN
LET LEGENDRERECURSIVE=FUNC(XX)
ELSE
FOR I=1 TO N
LET XX(LEV)=X(I)*(B(LEV)-A(LEV))/2+(A(LEV)+B(LEV))/2
LET WW(LEV)=W(I)*(B(LEV)-A(LEV))/2
LET S=S+LEGENDRERECURSIVE(LEV-1,XX,WW,A,B,N)*WW(LEV)
NEXT I
LET LEGENDRERECURSIVE=S
END IF
END FUNCTION
EXTERNAL FUNCTION FUNC(X())
LET S=1
FOR I=1 TO LEVEL
LET S=S-X(I)*X(I)
NEXT I
IF S > 0 THEN
LET FUNC=SQR(S)
ELSE
LET FUNC=0
END IF
END FUNCTION
PUBLIC NUMERIC LEVEL
INPUT PROMPT "多重積分 LEVEL=":LEVEL
DIM A(LEVEL),B(LEVEL),N(LEVEL),X(LEVEL),W(LEVEL)
FOR I=1 TO LEVEL
!'INPUT PROMPT "下限 =":A(I)
!'INPUT PROMPT "上限 =":B(I)
!'INPUT PROMPT "分割数=":N(I)
READ A(I),B(I),N(I)
NEXT I
DATA 0,1,10
DATA 0,1,10
DATA 0,1,10
DATA 0,1,10
PRINT TCHEBYCHEFFRECURSIVE(LEVEL,X,W,A,B,N)
END
EXTERNAL FUNCTION TCHEBYCHEFFRECURSIVE(LEV,XX(),WW(),A(),B(),N())
IF LEV=0 THEN
LET TCHEBYCHEFFRECURSIVE=FUNC(XX)
ELSE
FOR I=0 TO N(LEV)-1
LET XX(LEV)=COS((2*I+1)/2/N(LEV)*PI)*(B(LEV)-A(LEV))/2+(A(LEV)+B(LEV))/2
LET WW(LEV)=SQR((B(LEV)-XX(LEV))*(XX(LEV)-A(LEV)))
LET S=S+TCHEBYCHEFFRECURSIVE(LEV-1,XX,WW,A,B,N)*WW(LEV)
NEXT I
LET TCHEBYCHEFFRECURSIVE=S*PI/N(LEV)
END IF
END FUNCTION
EXTERNAL FUNCTION FUNC(X())
LET S=1
FOR I=1 TO LEVEL
LET S=S-X(I)*X(I)
NEXT I
IF S > 0 THEN
LET FUNC=SQR(S)
ELSE
LET FUNC=0
END IF
END FUNCTION
PUBLIC NUMERIC LEVEL
INPUT PROMPT "多重積分 LEVEL=":LEVEL
DIM X(LEVEL)
PRINT DE(LEVEL,X,1/16);PI^(LEVEL/2)
END
EXTERNAL FUNCTION DE(LEV,X(),H)
IF LEV=0 THEN
LET DE=FUNC(X)
ELSE
FOR K=-4 TO 4 STEP H !'(要)調整 K=-6〜6,H=1/1000 程度
LET X(LEV)=Q(K)
LET S=S+H*DE(LEV-1,X,H)*QQ(K)
NEXT K
LET DE=S
END IF
END FUNCTION
EXTERNAL FUNCTION Q(X)
LET Q=SINH(PI/2*SINH(X))
END FUNCTION
EXTERNAL FUNCTION QQ(X)
LET QQ=PI/2*COSH(X)*COSH(PI/2*SINH(X))
END FUNCTION
EXTERNAL FUNCTION FUNC(X())
LET S=0
FOR I=1 TO LEVEL
LET S=S-X(I)*X(I)
NEXT I
LET FUNC=EXP(S)
END FUNCTION
RANDOMIZE
PUBLIC NUMERIC LEVEL
INPUT PROMPT "多重積分 LEVEL=":LEVEL
DIM A(LEVEL),B(LEVEL),N(LEVEL),AA(LEVEL)
FOR I=1 TO LEVEL
!'INPUT PROMPT "下限 =":A(I)
!'INPUT PROMPT "上限 =":B(I)
!'INPUT PROMPT "分割数=":N(I)
READ A(I),B(I),N(I)
NEXT I
PRINT MONTE(LEVEL,A,B,10000)
!'PRINT MONTE2(LEVEL,A,B,10000,2000)
!'PRINT MONTESIMPSON(LEVEL,A,B,10000)
!'PRINT MONTERECURSIVE(LEVEL,AA,A,B,N)
DATA 0,1,50
DATA 0,1,50
DATA 0,1,50
DATA 0,1,50
END
EXTERNAL FUNCTION MONTE(LEV,A(),B(),N)
RANDOMIZE
DIM AA(LEV)
LET H=1
FOR I=1 TO LEV
LET H=H*(B(I)-A(I))
NEXT I
FOR K=1 TO N
FOR I=1 TO LEV
LET AA(I)=A(I)+(B(I)-A(I))*RND
NEXT I
LET S=S+FUNC(AA)
NEXT K
LET MONTE=H*S/N
END FUNCTION
EXTERNAL FUNCTION MONTE2(LEV,A(),B(),N,NN)
RANDOMIZE
DIM AA(LEV)
LET HMAX=-MAXNUM
LET HMIN=MAXNUM
LET HH=1
FOR I=1 TO LEV
LET HH=HH*(B(I)-A(I))
NEXT I
FOR K=1 TO NN
FOR J=1 TO LEV
LET AA(J)=A(J)+(B(J)-A(J))*RND
NEXT J
LET H=FUNC(AA)
LET HMIN=MIN(HMIN,MIN(H,0))
LET HMAX=MAX(H,HMAX)
NEXT K
LET H=HMAX-HMIN
FOR K=1 TO N
FOR J=1 TO LEV
LET AA(J)=A(J)+(B(J)-A(J))*RND
NEXT J
LET Z=H*RND+HMIN
IF FUNC(AA) > 0 THEN
IF Z > 0 AND Z < FUNC(AA) THEN LET M1=M1+1
ELSE
IF Z < 0 AND Z > FUNC(AA) THEN LET M2=M2+1
END IF
NEXT K
LET MONTE2=HH*(M1-M2)/N*H
END FUNCTION
EXTERNAL FUNCTION MONTERECURSIVE(LEV,AA(),A(),B(),N()) !'再帰式モンテカルロ
IF LEV=0 THEN
LET MONTERECURSIVE=FUNC(AA)
ELSE
LET H=B(LEV)-A(LEV)
FOR K=1 TO N(LEV)
LET AA(LEV)=A(LEV)+H*RND
LET S=S+MONTERECURSIVE(LEV-1,AA,A,B,N)
NEXT K
LET MONTERECURSIVE=H*S/N(LEV)
END IF
END FUNCTION
EXTERNAL FUNCTION MONTESIMPSON(LEV,A(),B(),N) !'モンテカルロ+シンプソン則
RANDOMIZE
DIM AA(LEV),T(LEV),HH(LEV)
LET H=1
FOR I=1 TO LEV
LET H=H*(B(I)-A(I))
LET HH(I)=(B(I)-A(I))/N/2
NEXT I
FOR K=1 TO N
FOR I=1 TO LEV
LET T(I)=(B(I)-A(I))*RND+A(I)
LET AA(I)=A(I)+T(I)
NEXT I
LET S=S+1/3*H*FUNC(AA)
FOR I=1 TO LEVEL
LET AA(I)=A(I)+HH(I)+T(I)
NEXT I
LET S=S+4/3*H*FUNC(AA)
FOR I=1 TO LEVEL
LET AA(I)=A(I)+2*HH(I)+T(I)
NEXT I
LET S=S+1/3*H*FUNC(AA)
NEXT K
LET MONTESIMPSON=S/N/2
END FUNCTION
EXTERNAL FUNCTION FUNC(X())
LET S=1
FOR I=1 TO LEVEL
LET S=S-X(I)*X(I)
NEXT I
IF S > 0 THEN
LET FUNC=SQR(S)
ELSE
LET FUNC=0
END IF
END FUNCTION
PUBLIC NUMERIC LEVEL
INPUT PROMPT "多重積分 LEVEL=":LEVEL
DIM X(LEVEL)
PRINT MONTEDE(LEVEL,X,10000);PI^(LEVEL/2)
END
EXTERNAL FUNCTION MONTEDE(LEV,X(),N) !'モンテカルロ + DE法
RANDOMIZE
LET M=4 !'(要) 調整
LET H=2*M/N
FOR J=1 TO N
LET V=1
FOR I=1 TO LEV
LET K=RND*M*2-M
LET X(I)=Q(K)
LET V=V*QQ(K)
NEXT I
LET S=S+H^LEV*FUNC(X)*V
NEXT J
LET MONTEDE=S*N^(LEV-1)
END FUNCTION
EXTERNAL FUNCTION FUNC(X())
FOR I=1 TO LEVEL
LET S=S-X(I)*X(I)
NEXT I
LET FUNC=EXP(S)
END FUNCTION
EXTERNAL FUNCTION Q(X)
LET Q=SINH(PI/2*SINH(X))
END FUNCTION
EXTERNAL FUNCTION QQ(X)
LET QQ=PI/2*COSH(X)*COSH(PI/2*SINH(X))
END FUNCTION
!' S(n+2)=V(n)*2*π*r S(n)...n次元球の表面積
!' V(n)=S(n)*r/n V(n)...n次元球の体積
!' V(n)=π^(n/2)/GAMMA(n/2+1)*r^n
LET MAXLEVEL=20
DIM S(MAXLEVEL+2),V(MAXLEVEL+2)
INPUT PROMPT "半径=":R !' 検証時 R=.5
LET S(2)=2*PI*R
LET V(2)=PI*R^2
LET S(3)=4*PI*R^2
LET V(3)=4/3*PI*R^3
FOR N=2 TO MAXLEVEL
LET S(N+2)=V(N)*2*PI*R
LET V(N+2)=S(N+2)*R/(N+2)
PRINT N;"次元球の体積";V(N) !';TAB(40);"表面積";S(N)
NEXT N
END
--- おまけ ---
有理数モードでお試しください
LET MAXLEVEL=20
DIM S(MAXLEVEL+2,3),V(MAXLEVEL+2,3)
LET S(2,1)=2
LET S(2,2)=1
LET S(2,3)=1
LET S(3,1)=4
LET S(3,2)=1
LET S(3,3)=2
LET V(2,1)=1
LET V(2,2)=1
LET V(2,3)=2
LET V(3,1)=4/3
LET V(3,2)=1
LET V(3,3)=3
FOR N=2 TO MAXLEVEL
LET S(N+2,1)=V(N,1)*2
LET S(N+2,2)=V(N,2)+1
LET S(N+2,3)=V(N,3)+1
LET V(N+2,1)=S(N+2,1)/(N+2)
LET V(N+2,2)=S(N+2,2)
LET V(N+2,3)=S(N+2,3)+1
PRINT STR$(N);"次元球の体積 ";
IF V(N,1)<>1 THEN LET A$=STR$(V(N,1)) & "*" ELSE LET A$=""
IF V(N,2)=1 THEN LET P$="π" ELSE LET P$="π^" & STR$(V(N,2))
IF V(N,3)=1 THEN LET R$="*r" ELSE LET R$="*r^" & STR$(V(N,3))
PRINT A$;P$;R$
PRINT STR$(N);"次元球の表面積 ";
IF S(N,1)<>1 THEN LET A$=STR$(S(N,1)) & "*" ELSE LET A$=""
IF S(N,2)=1 THEN LET P$="π" ELSE LET P$="π^" & STR$(S(N,2))
IF S(N,3)=1 THEN LET R$="*r" ELSE LET R$="*r^" & STR$(S(N,3))
PRINT A$;P$;R$
PRINT
NEXT N
END
--- おまけ 2---
!'n次元球の体積
!'V(n)=1/(1*3*5*7*..*N)*2^((N+1)/2)*π^((N-1)/2)*R^N ...MOD(N,2)=1
!'V(n)=1/(2*4*6*8*..*N)*2^(N/2) *π^(N/2) *R^N ...MOD(N,2)=0
LET MAXLEVEL=20
FOR N=2 TO MAXLEVEL
LET S=1
FOR I=N TO 2 STEP -2
LET S=S/I
NEXT I
PRINT N;"次元球の体積 ";STR$(S*2^((N+MOD(N,2))/2));"*π^";STR$((N-MOD(N,2))/2);"*r^";STR$(N)
PRINT N;"次元球の表面積 ";STR$(N*S*2^((N+MOD(N,2))/2));"*π^";STR$((N-MOD(N,2))/2);"*r^";STR$(N-1)
PRINT
NEXT N
END
!7セグメント数字表示のデジタル時計(Clock)
LET w=400 !画面の大きさ
LET h=120
SET bitmap SIZE w+1,h+1 !ドット単位にする
SET WINDOW 0,w,h,0 !クライアント座標(左上が原点)
LET S0=-1
DO
LET t$=TIME$ !時刻をhh:mm:ss形式で得る
LET S=VAL(t$(7:8)) !秒
IF S<>S0 THEN !更新されたら
LET S0=S
LET H=VAL(t$(1:2)) !時
LET M=VAL(t$(4:5)) !分
CALL clock_display(INT(H/10),MOD(H,10),INT(M/10),MOD(M,10),INT(S/10),MOD(S,10))
END IF
LOOP
!電子部品(配置と配線)
! ↓BCD(h10,h1,m10,m1,s10,s1)
! ┌─ データラッチ
! │ ↓BCD
! │ デコーダ
! │ ↓abcdefg
! └→ 88:88:88
! │
! GND
SUB clock_display(h10,h1,m10,m1,s10,s1) !表示部
SET DRAW mode hidden !ちらつき防止(開始)
CLEAR
DRAW LED(1,GND) WITH SCALE(20)*SHIFT(155,40) !コロン
DRAW LED(1,GND) WITH SCALE(20)*SHIFT(155,80)
!ダイナミック点灯表示
DRAW DRIVER7segment(h10) WITH SCALE(20)*SHIFT(50,60) !時
DRAW DRIVER7segment(h1) WITH SCALE(20)*SHIFT(110,60)
DRAW DRIVER7segment(m10) WITH SCALE(20)*SHIFT(200,60) !分
DRAW DRIVER7segment(m1) WITH SCALE(20)*SHIFT(260,60)
DRAW DRIVER7segment(s10) WITH SCALE(15)*SHIFT(320,70) !秒
DRAW DRIVER7segment(s1) WITH SCALE(15)*SHIFT(370,70)
SET DRAW mode explicit !ちらつき防止(終了)
END SUB
PICTURE DRIVER7segment(BCD) !7セグメント数字表示にする
CALL DECODE7segment(BCD, Za,Zb,Zc,Zd,Ze,Zf,Zg)
DRAW LED7segmentKwithoutDP(Za,Zb,Zc,Zd,Ze,Zf,Zg)
END PICTURE
!電子部品(上位)
SUB DECODE7segment(n, Za,Zb,Zc,Zd,Ze,Zf,Zg) !7セグメント数字表示デコーダ
IF n=0 THEN
LET ptn$="1111110" !abcdedfgのオン・オフ状態
ELSEIF n=1 THEN
LET ptn$="0110000"
ELSEIF n=2 THEN
LET ptn$="1101101"
ELSEIF n=3 THEN
LET ptn$="1111001"
ELSEIF n=4 THEN
LET ptn$="0110011"
ELSEIF n=5 THEN
LET ptn$="1011011"
ELSEIF n=6 THEN
LET ptn$="1011111"
ELSEIF n=7 THEN
LET ptn$="1110000"
ELSEIF n=8 THEN
LET ptn$="1111111"
ELSEIF n=9 THEN
LET ptn$="1111011"
ELSE
PRINT "不正な値です。"; n
END IF
LET Za=VAL(ptn$(1:1))
LET Zb=VAL(ptn$(2:2))
LET Zc=VAL(ptn$(3:3))
LET Zd=VAL(ptn$(4:4))
LET Ze=VAL(ptn$(5:5))
LET Zf=VAL(ptn$(6:6))
LET Zg=VAL(ptn$(7:7))
END SUB
! --a- 配置位置
! f| |b
! --g-
! e| |c
! --d-
PICTURE LED7segmentKwithoutDP(a,b,c,d,e,f,g) !7セグメント数字表示器 ※カソード・コモン
DRAW bar(a,GND) WITH SHIFT(0,-2) !※左上が原点
DRAW bar(b,GND) WITH ROTATE(PI/2)*SHIFT(1,-1)
DRAW bar(c,GND) WITH ROTATE(PI/2)*SHIFT(1,1)
DRAW bar(d,GND) WITH SHIFT(0,2)
DRAW bar(e,GND) WITH ROTATE(PI/2)*SHIFT(-1,1)
DRAW bar(f,GND) WITH ROTATE(PI/2)*SHIFT(-1,-1)
DRAW bar(g,GND) WITH SHIFT(0,0)
END PICTURE
!電子部品(下位)
PICTURE bar(a,k) !発光ダイオードを表示する
IF a=1 AND k=0 THEN
PLOT AREA: -1,-0.3; 1,-0.3; 1,0.3; -1,0.3 !点灯 ※塗り潰し
ELSE
PLOT LINES: -1,-0.2; 1,-0.2; 1,0.2; -1,0.2; -1,-0.2 !消灯 ※枠
END IF
END PICTURE
PICTURE LED(a,k) !発光ダイオードを表示する
IF a=1 AND k=0 THEN
DRAW disk WITH SCALE(0.4) !点灯
ELSE
DRAW circle WITH SCALE(0.4) !消灯
END IF
END PICTURE
END
! 山中さんの7セグ数字で、気が付いた。ありがとうございます。
! plot_lines の、vector_fontで、PLOT TEXT を、カバーできた。
! やや長文と、やせた字形は難点ながら、時計の数字も、鏡像になった。
!
!-------------------
LET N=2
LET NN=2^N
SET WINDOW -250/NN,250/NN,250/NN,-250/NN
SET TEXT COLOR 4
SET TEXT BACKGROUND "OPAQUE"
LET φ=0
LET stp=-PI/180*6
DO
LET t=INT(TIME)
IF t0<>t THEN
LET t0=t
IF 2*PI<=ABS(φ) THEN LET stp=-stp
LET φ=REMAINDER(φ, 2*PI) +stp
!-----
SET DRAW mode hidden
CLEAR
DRAW D4(N) WITH SHIFT(-300/2,-300/2/SQR(3))*ROTATE(φ*(-1)^N)*SCALE(1,(-1)^N)
DRAW center WITH SHIFT(-300/2/NN,-300/2/NN/SQR(3))*ROTATE(φ)
PLOT TEXT,AT 137/NN,-234/NN:"右クリックで停止"
SET DRAW mode explicit
ELSE
WAIT DELAY 0.05 ! 省電力効果
END IF
MOUSE POLL mx,my,mlb,mrb
LOOP UNTIL mrb>=1 ! 右クリックで停止
PICTURE center
SET LINE COLOR 2
SET LINE width 2
PLOT LINES:0,0;300/NN,0;300/2/NN,300/2/NN*SQR(3);0,0
SET LINE width 1
SET LINE COLOR 1
END PICTURE
!------
PICTURE D4(k)
IF 0< k THEN
DRAW D4(k-1) WITH SCALE(1/2,1/2)*SHIFT(300/4,SQR(3)*300/4) ! 内側の上
DRAW D4(k-1) WITH SCALE(1/2,-1/2)*SHIFT(300/4,SQR(3)*300/4) ! 内側の中
DRAW D4(k-1) WITH SCALE(1/2,1/2)*ROTATE(-PI*2/3)*SHIFT(300/4,SQR(3)*300/4) !内側の左
DRAW D4(k-1) WITH SCALE(1/2,1/2)*ROTATE(PI*2/3)*SHIFT(300,0) ! 内側の右
ELSE
DRAW 時計図 WITH ROTATE(-φ)*SHIFT(300/2,300/2/SQR(3))
PLOT LINES:0,0;300,0;300/2,SQR(3)*300/2;0,0 ! 外側の基準三角形(直接の描画は無し。)
END IF
END PICTURE
!------
PICTURE 時計図
SET AREA COLOR 1
FOR i=1 TO 60
LET a=PI/30*(i-15)
IF MOD(i,5)=0 THEN
CALL linefont(i/5, 60*COS(a), 60*SIN(a)) !数字
DRAW disk WITH SCALE(1)*SHIFT(72*COS(a),72*SIN(a)) !5分目盛り
ELSE
DRAW disk WITH SCALE(.5)*SHIFT(72*COS(a),72*SIN(a)) !1分目盛り
END IF
NEXT i
!--- 00:00 からt秒 の針回転 Gear
DRAW hand(1) WITH SCALE(2.5, 0.75)*ROTATE(t*PI/21600) ! 時針
DRAW hand(1) WITH ROTATE(t*PI/1800) ! 分針
DRAW hand(2) WITH SCALE(0, 1.1)*ROTATE(t*PI/30) ! 秒針
!--- 中心の飾り
DRAW disk WITH SHIFT(0,0)*SCALE(4)
END PICTURE
PICTURE hand(c) ! 3針共用
SET AREA COLOR c
PLOT AREA: -1,15; 1,15; 1,-60; -1,-60
END PICTURE
!-------------------------------------
SUB linefont(i,x,y) ! plot text の代替
SELECT CASE i
CASE 1
PLOT LINES:x+2.6,y-5;x+2.6,y+5 ! 1
CASE 2
PLOT LINES:x-2.6,y-5;x+2.6,y-5;x+2.6,y;x-2.6,y;x-2.6,y+5;x+2.6,y+5 ! 2
CASE 3
PLOT LINES:x-2.6,y-5;x+2.6,y-5;x+2.6,y+5;x-2.6,y+5 ! 3a
PLOT LINES:x-2.6,y;x+2.6,y ! 3b
CASE 4
PLOT LINES:x-2.6,y-5;x-2.6,y;x+2.6,y ! 4a
PLOT LINES:x+2.6,y-5;x+2.6,y+5 ! 4b
CASE 5
PLOT LINES:x+2.6,y-5;x-2.6,y-5;x-2.6,y;x+2.6,y;x+2.6,y+5;x-2.6,y+5 ! 5
CASE 6
PLOT LINES:x+2.6,y-5;x-2.6,y-5;x-2.6,y+5;x+2.6,y+5;x+2.6,y;x-2.6,y ! 6
CASE 7
PLOT LINES:x-2.6,y-5;x+2.6,y-5;x+2.6,y+5 ! 7
CASE 8
PLOT LINES:x-2.6,y;x-2.6,y-5;x+2.6,y-5;x+2.6,y+5;x-2.6,y+5;x-2.6,y;x+2.6,y ! 8
CASE 9
PLOT LINES:x+2.6,y;x-2.6,y;x-2.6,y-5;x+2.6,y-5;x+2.6,y+5;x-2.6,y+5 ! 9
CASE 10
LET x=x-7
PLOT LINES:x+2.6,y-5;x+2.6,y+5 ! 1
LET x=x+11
PLOT LINES:x-2.6,y+5;x-2.6,y-5;x+2.6,y-5;x+2.6,y+5;x-2.6,y+5 ! 0
CASE 11
LET x=x-5
PLOT LINES:x+2.6,y-5;x+2.6,y+5 ! 1
LET x=x+9
PLOT LINES:x+2.6,y-5;x+2.6,y+5 ! 1
CASE 12
LET x=x-7
PLOT LINES:x+2.6,y-5;x+2.6,y+5 ! 1
LET x=x+11
PLOT LINES:x-2.6,y-5;x+2.6,y-5;x+2.6,y;x-2.6,y;x-2.6,y+5;x+2.6,y+5 ! 2
CASE ELSE
END SELECT
END SUB
SECONDさんのプログラムの3行目のSET WINDOW文の後ろにつぎのプログロムを挿入してみてください。既存のSUB linefontは廃してください。
Century体は日本語に対応してないので"右クリックで停止"を"Right Click to Stop"にもどしてください。
MAT PLOT文は3次元の配列には適応してないので、あまりスマートではないですがなんとか1秒以内に描画できると思います。遅れる場合は文字サイズ(th=13)を小さくしてみて下さい。
!
ASK TEXT HEIGHT ath
ASK TEXT JUSTIFY atjx$,atjy$
SET POINT STYLE 1
SET TEXT JUSTIFY "CENTER","HALF"
LET th=13
SET TEXT HEIGHT th
SET TEXT FONT "Century" ,0
ASK TEXT WIDTH("WW") tw
ASK PIXEL SIZE (0,0;1.2*th,1.2*tw) px,py
LET p=ABS(px*py)
DIM f0(p,2),f1(p,2),f2(p,2),f3(p,2),f4(p,2),f5(p,2),f6(p,2),f7(p,2),f8(p,2),f9(p,2),f10(p,2),f11(p,2),f12(p,2)
LET pitchx=WORLDX(PIXELX(0)+1)
LET pitchy=WORLDY(PIXELY(0)+1)
FOR i=1 TO 12
PLOT TEXT ,AT 0,0 : STR$(i)
MAT f0=ZER
LET k=0
FOR x=-0.6*tw TO 0.6*tw STEP pitchx
FOR y=0.6*th TO -0.6*th STEP pitchy
ASK PIXEL VALUE (x,y) pc
IF pc=1 THEN ! 中間色(灰色)を読み込むなら条件を pc<>0
LET k=k+1
LET f0(k,1)=x
LET f0(k,2)=y
END IF
NEXT y
NEXT x
CALL font_read
CLEAR
NEXT i
SET TEXT HEIGHT ath
SET TEXT JUSTIFY atjx$,atjy$
!
SUB font_read
MAT f12=ZER(k,2)
FOR j=1 TO k
LET f12(j,1)=f0(j,1)
LET f12(j,2)=f0(j,2)
NEXT j
SELECT CASE i
CASE 1
MAT f1=f12
CASE 2
MAT f2=f12
CASE 3
MAT f3=f12
CASE 4
MAT f4=f12
CASE 5
MAT f5=f12
CASE 6
MAT f6=f12
CASE 7
MAT f7=f12
CASE 8
MAT f8=f12
CASE 9
MAT f9=f12
CASE 10
MAT f10=f12
CASE 11
MAT f11=f12
CASE ELSE
END SELECT
END SUB
SUB linefont(fi,x,y)
SELECT CASE fi
CASE 1
DRAW numplot(f1) WITH SHIFT(x,y)
CASE 2
DRAW numplot(f2) WITH SHIFT(x,y)
CASE 3
DRAW numplot(f3) WITH SHIFT(x,y)
CASE 4
DRAW numplot(f4) WITH SHIFT(x,y)
CASE 5
DRAW numplot(f5) WITH SHIFT(x,y)
CASE 6
DRAW numplot(f6) WITH SHIFT(x,y)
CASE 7
DRAW numplot(f7) WITH SHIFT(x,y)
CASE 8
DRAW numplot(f8) WITH SHIFT(x,y)
CASE 9
DRAW numplot(f9) WITH SHIFT(x,y)
CASE 10
DRAW numplot(f10) WITH SHIFT(x,y)
CASE 11
DRAW numplot(f11) WITH SHIFT(x,y)
CASE 12
DRAW numplot(f12) WITH SHIFT(x,y)
END SELECT
END SUB
PICTURE numplot(fm(,))
MAT PLOT POINTS : fm
END PICTURE
!
!
! Knight's Tour(ナイト・ツアー)
!
! 注意!出発点に戻る経路 Closed Tour のみに、限定して計算。⇔Open Tour
!
! KNIGHTGR.UB
! Original Version 1990/10/01 by unknown
! Modified Version 1997/04/10 by Aiichi Yamasaki
! Modified Version 2009/01/06 uBASIC から、十進Basic へ移植。
!--------------------
OPTION BASE 0
SET TEXT background "OPAQUE"
SET POINT STYLE 4
!
LET DF=0 ! 0:通常 1:探索過程のstep 2:探索完了毎のstep //debug
LET Xw=6 !8 ! 盤の横巾
LET Yw=6 !8 ! 盤の縦巾
!-----
! Schwenk's Theorem
! For any m × n board with m less than or equal to n,
! a closed knight's tour is always possible
! unless one or more of these three conditions are true:
!1)m and n are both odd
!2)m = 1, 2, or 4; m and n are not both 1
!3)m = 3 and n = 4, 6, or 8
!
LET m= MIN(Xw,Yw)
LET n= MAX(Xw,Yw)
!
IF MOD(m,2)=1 AND MOD(n,2)=1 THEN CALL outer
IF (m=1 OR m=2 OR m=4) AND (m<>1 OR n<>1) THEN CALL outer
IF m=3 AND (n=4 OR n=6 OR n=8) THEN CALL outer
SUB outer
beep
PRINT "Xw=";Xw;"Yw=";Yw;" … No Closed Tour."
STOP
END SUB
!-----
LET D0=INT(192/MAX(MAX(Xw,Yw),8)) ! 盤の1目幅
SET WINDOW -55/D0, 445/D0, 370/D0,-130/D0
PLOT TEXT,AT 0,-50/D0:"Knight's Tour"
LET Xct= 0
LET Yct= -30/D0 ! count--time の位置
CALL guide( 205/D0, 10/D0) ! x,y
!-----init
DIM P_(-2 TO Yw+1,-2 TO Xw+1), E_(-2 TO Yw+1,-2 TO Xw+1), I_(Xw*Yw), DX_(7), DY_(7)
MAT READ DX_,DY_
DATA 2, 1,-1,-2,-2,-1, 1, 2
DATA 1, 2, 2, 1,-1,-2,-2,-1
!-----
IF DF<>0 THEN MAT PRINT USING REPEAT$("## ",8): DX_ ! //debug
IF DF<>0 THEN MAT PRINT USING REPEAT$("## ",8): DY_ ! //debug
!-----init P_
MAT P_=CON
FOR y=0 TO Yw-1
FOR x=0 TO Xw-1
LET P_(y,x)=0
NEXT x
NEXT y
!-----init E_
MAT E_=20*CON
FOR y=0 TO Yw-1
FOR x=0 TO Xw-1
LET E_(y,x)=0
NEXT x
NEXT y
FOR y=0 TO Yw-1
FOR x=0 TO Xw-1
LET c=8
FOR i=0 TO 7
LET c=c-P_(y+DY_(i),x+DX_(i))
NEXT i
LET E_(y,x)=c
NEXT x
NEXT y
!-----
IF DF<>0 THEN MAT PRINT USING REPEAT$(" ##",Xw+4) :P_ ! //debug
IF DF<>0 THEN MAT PRINT USING REPEAT$(" ##",Xw+4) :E_ ! //debug
!-----
LET sp=0 ! 0~(Xw*Yw-1) 階層位置(再帰型のStackPointerに相当)
LET xx=0 ! 開始地点
LET yy=0 ! (0,0)
LET I_(sp)=-1 ! 全階層の方向カウンター
LET Count=0
LET t0=TIME
IF DF<>0 THEN CALL PUTL(xx,yy,0,0,2) ! //debug
DO
LET I_(sp)=I_(sp)+1
LET ii=I_(sp)
IF 7< ii THEN
CALL BACK ! 1層戻す。
ELSE
IF P_(yy+DY_(ii),xx+DX_(ii))=0 THEN ! 重複検査。
IF DF<>0 THEN CALL PUTL(xx,yy,DX_(ii),DY_(ii),2) ! //debug
LET xx=xx+DX_(ii)
LET yy=yy+DY_(ii)
LET P_(yy,xx)=1
!-----dec E_
LET E_(yy,xx)= E_(yy,xx)+10
FOR i=0 TO 7
LET E_(yy+DY_(i),xx+DX_(i))= E_(yy+DY_(i),xx+DX_(i))-1
NEXT i
IF DF<>0 THEN CALL DISP_E ! 探索過程の配列 E_ モニター //debug
!----- 1層進める。
LET sp=sp+1
LET I_(sp)=-1
IF sp=Xw*Yw THEN
CALL FIN ! 1経路の完成。
CALL BACK ! 1層戻す。
ELSEIF fnCHECK(xx,yy)<>0 THEN ! 次の重複検査前の、予見検査。
CALL BACK ! 1層戻す。
END IF
END IF
END IF
LOOP
SUB BACK
LET P_(yy,xx)=0
!-----inc E_
LET E_(yy,xx)= E_(yy,xx)-10
FOR i=0 TO 7
LET E_(yy+DY_(i),xx+DX_(i))= E_(yy+DY_(i),xx+DX_(i))+1
NEXT i
!-----
LET sp=sp-1
IF sp=0 THEN STOP ! 終了、Count:1倍
!IF sp< 0 THEN STOP ! 終了、Count:2倍(開始点も回転、帰路まで別経路になる)
LET ii=I_(sp)
LET xx=xx-DX_(ii)
LET yy=yy-DY_(ii)
IF DF<>0 THEN CALL PUTL(xx,yy,DX_(ii),DY_(ii),0) ! //debug
END SUB
FUNCTION fnCHECK(x,y) ! 予見検査。
LET c=0
IF sp< Xw*Yw-1 THEN
LET fnCHECK=1 ! 帰りの引数=1
IF ABS(I_(1)-I_(0))=4 THEN EXIT FUNCTION !return(1)
FOR i=0 TO 7
IF E_(y+DY_(i),x+DX_(i))< 2 THEN
IF E_(y+DY_(i),x+DX_(i))=0 THEN EXIT FUNCTION !return(1)
LET c=c-1
END IF
NEXT i
IF c< -1 THEN
IF sp<>1 THEN EXIT FUNCTION !return(1)
END IF
FOR y=0 TO Yw-1
FOR x=0 TO Xw-1
IF E_(y,x)< 2 THEN
IF E_(y,x)=0 THEN EXIT FUNCTION !return(1)
LET c=c+1
IF c>1 THEN EXIT FUNCTION !return(1)
END IF
NEXT x
NEXT y
END IF
LET fnCHECK=0 ! 帰りの引数=0
END FUNCTION !return(0)
SUB PUTL(x,y,dx,dy,c)
SET LINE COLOR c
PLOT LINES: x,y; x+dx,y+dy
PLOT POINTS: x+dx,y+dy
END SUB
SUB DISP_E
PRINT
MAT PRINT USING REPEAT$(" ##",Xw+4) :E_
IF DF=1 THEN pause ! //debug
END SUB
SUB FIN
!-----disp_A
SET AREA COLOR 0
PLOT AREA :0,0; Xw-1,0; Xw-1,Yw-1; 0,Yw-1
LET x=0
LET y=0
CALL PUTL(x,y,0,0,2)
FOR s=0 TO Xw*Yw-1
CALL PUTL(x,y,DX_(I_(s)),DY_(I_(s)),2)
LET x=x+DX_(I_(s))
LET y=y+DY_(I_(s))
NEXT s
!-----disp cout--time
LET Count=Count+1
LET t1=INT(TIME-t0)
IF t1< 0 THEN LET t1=t1+86400
PLOT TEXT,AT Xct,Yct :"count= "& STR$(Count)& " ----- "&
&& USING$("%%",MOD(INT(t1/3600),24))& ":"&
&& USING$("%%",MOD(INT(t1/60),60))& ":"& USING$("%%",MOD(t1,60))
IF DF=2 THEN pause ! //debug
END SUB
!----------ガイド表示-----
SUB guide(x,y)
PLOT TEXT,AT x,y: "H V 一巡する経路の数"
PLOT TEXT,AT x,y +20/D0,USING "3x4: can't close ### open 参考": 2
PLOT TEXT,AT x,y +40/D0,USING "5x5: can't close ### open 参考": 304
PLOT TEXT,AT x,y +60/D0,USING "5x6: ##,###,###,###,### closed": 8
PLOT TEXT,AT x,y +80/D0,USING "6x6: ##,###,###,###,### closed": 9862
PLOT TEXT,AT x,y+100/D0,USING "8x8: ##,###,###,###,### closed": 26534728821064
!
PLOT TEXT,AT x,y+140/D0:"Knight の移動規則"
LET x=x+2
LET y=y+160/D0+2
SET LINE COLOR 2
SET AREA COLOR 2
LET j=SQR(5)
FOR i=ATN(0.5) TO 2*PI STEP PI/2
DRAW knight WITH ROTATE(i)*SHIFT(x,y)
DRAW knight WITH ROTATE(-i)*SHIFT(x,y)
NEXT i
FOR j=-2 TO 2
FOR i=-2 TO 2
PLOT POINTS: x+i, y+j
NEXT i
NEXT j
END SUB
DIM A(100),B(100),C(100)
LET m=3
LET n=8
MAT A=ZER(m)
MAT B=ZER(m*n)
MAT C=ZER(m TO n)
ところがMAT文では添字の下限を変更することはできないため、Cの下限は1,上限は6(=n-m+1)になります。
ヘルプでは『添字の下限を変えたいときは,MAT READ文か,拡張機能のMAT REDIM文を用いる。』とあります。
MAT READ C(m TO n) とすればよいわけですが、DATA文を読ませる必要があります。
MAT REDIM C(m TO n) ならば配列要素はそのままで添字の下限を変更できますがJIS規格外です。
次の外部副プログラム redim は、MAT REDIM文と同様の機能を持ちます。
DECLARE EXTERNAL SUB redim
DIM A(100)
LET m=3
LET n=8
CALL redim(A,m,n) ! MAT REDIM A(m TO n)と同義
PRINT LBOUND(A),UBOUND(A)
END
!
EXTERNAL SUB redim(p(),m,n) !配列の添字の上下限を再定義
WHEN EXCEPTION IN
DIM q(10000)
MAT q=p
MAT READ p(m TO n)
DATA 0
USE
END WHEN
FOR i=m TO n
LET p(i)=q(LBOUND(q)+i-m)
NEXT i
END SUB
!-----
LET g= 9.8 ! m/s^2 重力加速度
LET m1=.188 ! kg おもり
LET m2=.188 ! kg
LET L1= 5 ! m 吊り棒
LET L2= 5 ! m
LET r1=.75*SQR(m1) ! おもりの描画径
LET r2=.75*SQR(m2)
!
LET dt=0.05 !sec. 演算ピッチ。高速機 ほど、小さく。(0.05は、Pentium3 500MHz)
!
!※0.01くらいが望ましいが、描画ピッチ(画面に表示)が、ついて来れなくなったら戻す。
! 2つのピッチが、ズレていると物理的な速度ではなくなる。
!
!------------ 2重振り子の方程式
! d(dθ1)/dt^2=
! [ g*{sinθ2*cosΔ-μ*sinθ1}-{L2*(θ2/dt)^2+L1*(θ1/dt)^2*cosΔ}*sinΔ]
! /[ L1*{μ-cosΔ^2}]
! d(dθ2)/dt^2=
! [ g*μ*{sinθ1*cosΔ-sinθ2}+{μ*L1*(θ1/dt)^2+L2*(θ2/dt)^2*cosΔ}*sinΔ]
! /[ L2*{μ-cosΔ^2}]
!
! g= 重力加速度 μ=(m1+m2)/m2 Δ=θ1-θ2
!
!---------- 式の整理(θ1θ2 共に、重力方向0からの左回り角)
LET μ2=m2/(m1+m2)
LET L21=L2/L1
!
!ss1=-g/L1*sinθ1 -μ2*L21*ω2^2*sinΔ
!ss2=-g/L2*sinθ2 + ω1^2*sinΔ/L21
!D=1-μ2*COSΔ^2
!d(θ1)/dt=ω1
!d(θ2)/dt=ω2
!d(ω1)/dt=[ ss1 - L21*μ2*cosΔ*ss2 ] /D
!d(ω2)/dt=[ -cosΔ/L21*ss1 + ss2 ] /D
!
!---------- 微分方程式のまま、ルンゲ・クッタ法で描画。
LET θ1=PI*0.8 ! 初期角度
LET θ2=PI*0.8
LET w1=0 ! 初期角速度
LET w2=0
!
DEF ss1(w2,θ1,θ2)=-g/L1*SIN(θ1) -μ2*L21*w2^2*SIN(θ1-θ2)
DEF ss2(w1,θ1,θ2)=-g/L2*SIN(θ2) + w1^2*SIN(θ1-θ2)/L21
DEF D(θ1,θ2)=1-μ2*COS(θ1-θ2)^2
!
DEF α1(w1,w2,θ1,θ2)=( ss1(w2,θ1,θ2) -L21*μ2*COS(θ1-θ2)*ss2(w1,θ1,θ2) )/D(θ1,θ2)
DEF α2(w1,w2,θ1,θ2)=(-ss1(w2,θ1,θ2)*COS(θ1-θ2)/L21 +ss2(w1,θ1,θ2) )/D(θ1,θ2)
SUB RungeKutta
LET w11=w1
LET w12=w2
LET α11=α1(w1,w2,θ1,θ2)
LET α12=α2(w1,w2,θ1,θ2)
!
LET w21=w1+α11*dt/2
LET w22=w2+α12*dt/2
LET α21=α1(w21,w22,θ1+w11*dt/2,θ2+w12*dt/2)
LET α22=α2(w21,w22,θ1+w11*dt/2,θ2+w12*dt/2)
!
LET w31=w1+α21*dt/2
LET w32=w2+α22*dt/2
LET α31=α1(w31,w32,θ1+w21*dt/2,θ2+w22*dt/2)
LET α32=α2(w31,w32,θ1+w21*dt/2,θ2+w22*dt/2)
!
LET w41=w1+α31*dt
LET w42=w2+α32*dt
LET α41=α1(w41,w42,θ1+w31*dt,θ2+w32*dt)
LET α42=α2(w41,w42,θ1+w31*dt,θ2+w32*dt)
!
LET θ1=θ1+(w11+2*w21+2*w31+w41)*dt/6
LET θ2=θ2+(w12+2*w22+2*w32+w42)*dt/6
LET w1=w1+(α11+2*α21+2*α31+α41)*dt/6
LET w2=w2+(α12+2*α22+2*α32+α42)*dt/6
END SUB
!----エネルギー・メーター
DEF ep1=m1*g*(L1-L1*COS(θ1)) !位置1
DEF em1=(L1*w1)^2*m1/2 !運動1
DEF ep2=m2*g*( (L1-L1*COS(θ1)+L2)-L2*COS(θ2) ) !位置2
DEF em2=( (L1*w1)^2+(L2*w2)^2-2*L1*w1*L2*w2*COS(PI+θ1-θ2) )*m2/2 !運動2
!
!----run
LET w=13
SET WINDOW -w,w,-w,w
SET COLOR MIX(15) .5,.5,.5
SET TEXT background "OPAQUE"
LET t0=TIME
DO
LET t=TIME
IF dt=<ABS(t-t0) THEN
SET DRAW mode hidden
CLEAR
DRAW grid(5,5)
PLOT TEXT,AT -w*0.92,w*0.9:"おもりのエネルギー[J]"
PLOT TEXT,AT -w*0.92,w*0.83:"位置1 運動1 位置2 運動2"
PLOT TEXT,AT -w*0.96,w*0.76,USING"##.#### ##.#### ##.#### ##.####":ep1,em1,ep2,em2
PLOT TEXT,AT -w*0.86,w*0.69,USING"##.#### ##.####":ep1+em1,ep2+em2
PLOT TEXT,AT -w*0.62,w*0.62,USING"##.####":ep1+em1+ep2+em2
PLOT TEXT,AT w*0.25,w*0.9:"マウス 右ボタンで、終了。"
PLOT TEXT,AT w*0.4,w*0.76,USING"演算ピッチ=#.### 秒":dt
PLOT TEXT,AT w*0.4,w*0.69,USING"描画ピッチ=#.### 秒":t-t0
LET t0=t
DRAW Pendulum0 WITH ROTATE(θ1)
CALL RungeKutta ! 次のθ1,θ2 へ更新
SET DRAW mode explicit
!stop
END IF
WAIT DELAY 0 ! 省電力効果
MOUSE POLL mx,my,mlb,mrb
LOOP UNTIL mrb=1
PICTURE Pendulum0
DRAW circle WITH SCALE(0.2)
DRAW Pendulum1(L1,r1,"1")
DRAW Pendulum1(L2,r2,"2") WITH ROTATE(θ2-θ1)*SHIFT(0,-L1)
END PICTURE
PICTURE Pendulum1(L,r,w$)
PLOT LINES: 0,0;0,-L
DRAW disk WITH SCALE(r)*SHIFT(0,-L)
PLOT TEXT,AT r, r-L:w$
END PICTURE
RANDOMIZE
LET N=6 !コインを投げる回数
DIM s(-N TO N) !点xに戻る回数
MAT s=ZER
LET iter=50000 !試行回数
FOR i=1 TO iter
LET x=0 !原点
FOR k=1 TO N !コインを投げる
IF RND<0.5 THEN LET x=x+1 ELSE LET x=x-1 !表なら+1、裏なら−1
NEXT k
LET s(x)=s(x)+1 !結果
NEXT i
FOR i=-N TO N !点xに戻る確率
PRINT i;s(i)/iter
NEXT i
PRINT
FOR i=-N TO N !場合の数
PRINT USING "###: ###.##": i,s(i)/s(N) !x=Nを1とする
NEXT i
END
LET x=0 !原点
LET k=(x+N)/2 !整数解があれば
IF k=INT(k) THEN
PRINT k; comb(N,k)*(1/2)^k*(1-1/2)^(N-k)
ELSE
PRINT "到達しません。"
END IF
END
投げる回数ごとの「場合の数」の一覧表は、パスカルの三角形をつくればよい。
!パスカルの三角形
LET N=10 !コインを投げる回数
LET a=1 !パスカルの三角形
LET b=0
LET c=1
DIM P(-N TO N) !数直線上の各点
MAT P=ZER
LET P(0)=1 !原点に位置付ける
FOR i=-N TO N !目盛り
PRINT USING " ####": i;
NEXT i
PRINT
FOR i=-N TO N !数直線
PRINT "----+";
NEXT i
PRINT
FOR i=0 TO N !指定回数
MAT PRINT USING(REPEAT$(" ####",2*N+1)): P; !現状
PRINT USING " ### 回の場合": i
LET T1=0 !左 ※左端
LET T2=P(-N) !中央
FOR x=-N TO N !左から右へ走査する
IF x+1>N THEN LET T3=0 ELSE LET T3=P(x+1) !右
LET P(x)=a*T1+b*T2+c*T3
LET T1=T2 !次へ
LET T2=T3
NEXT x
NEXT i
END
!九九表(乗算表)と〜数
!1の段 − 自然数
!2の段 − 偶数
!各段 − 倍数
LET N=9 !※書式(PRINT USING)の桁を調整すれば変更可能
DIM A(0 TO 2*N) !数列 An
DIM S(0 TO 2*N) !数列 Sn
!●平方数(四角数) n^2
MAT A=ZER
PRINT
FOR i=1 TO N
FOR j=1 TO N
LET t=i*j !乗算
IF i=j THEN !対角線上なら
PRINT USING "(####)": t;
LET A(i)=t
ELSE
PRINT USING " #### ": t;
END IF
NEXT j
PRINT
NEXT i
PRINT
!四角錐数(平方数の和)Square Pyramid Numbers
! Σ[k=1,n]k^2
! =1^2 + 2^2 + 3^2 + … + (n-1)^2 + n^2
! =n*(n+1)*(2*n+1)/6
MAT S=ZER
FOR i=1 TO N
LET S(i)=S(i-1)+A(i) !和 ※A()は上記の平方数
NEXT i
FOR i=1 TO N !〜数を表示する
PRINT S(i);
NEXT i
PRINT
PRINT
!奇数の和 1 + 3 + 5 + … + (2*n-3) + (2*n-1)
! Σ[k=1,n](2*k-1)
! =n^2
MAT S=ZER
FOR i=1 TO N
LET S(i)=A(i)-A(i-1) !階差 ※A()は上記の平方数
NEXT i
FOR i=1 TO N !〜数を表示する
PRINT S(i);
NEXT i
PRINT
PRINT
!●四面体数(三角数の和、三角錐数 tetrahedral number)
! Σ[k=1,n]k*(n-k+1)
! =1*n+2*(n-1)+3*(n-2)+ … +(n-1)*2+n*1
! =n*(n+1)*(n+2)/6
MAT A=ZER
PRINT
FOR i=1 TO N
FOR j=1 TO N
LET t=i*j !乗算
LET A(i+j-1)=A(i+j-1)+t !右斜め(/)に加算する
PRINT USING "####": t;
NEXT j
PRINT
IF i<N THEN PRINT " ";REPEAT$(" /",N-1) !行間
NEXT i
PRINT
FOR i=1 TO N !〜数を表示する
PRINT A(i);
NEXT i
PRINT
PRINT
!●立方数 n^3
MAT A=ZER
PRINT
FOR i=1 TO N
FOR j=1 TO N
LET t=i*j !乗算
IF i<j THEN !L字に加算する
LET A(j)=A(j)+t
PRINT USING "│####": t;
ELSE
LET A(i)=A(i)+t
PRINT USING " ####": t;
END IF
NEXT j
PRINT "│" !行末
PRINT REPEAT$("───",i);"┘";REPEAT$(" │",N-i) !行間
NEXT i
PRINT
FOR i=1 TO N !〜数を表示する
PRINT A(i);
NEXT i
PRINT
PRINT
!立方数の和
! Σ[k=1,n]k^3=(n*(n+1)/2)^2の導出
! 1*Σ[k=1,n]k + 2*Σ[k=1,n]k + 3*Σ[k=1,n]k + … + (n-1)*Σ[k=1,n]k + n*Σ[k=1,n]k
! =(1+2+ … +(n-1)+n)*Σ[k=1,n]k
! =(Σ[k=1,n]k)^2
PRINT
FOR i=1 TO N
FOR j=1 TO N
LET t=i*j !乗算
PRINT USING " ####": t;
NEXT j
PRINT " ←1段目の";i;"倍"
NEXT i
PRINT
MAT S=ZER
FOR i=1 TO N
LET S(i)=S(i-1)+A(i) !※A()は上記の立方数
NEXT i
FOR i=1 TO N !〜数を表示する
PRINT S(i);
NEXT i
PRINT
PRINT
END
!
! 一個の神経細胞(neuro)
! その カオス(chaos)を、探し、見る、ツール
!
!----------------------------
! "Neuro12"
!
! 2009.1.18
!----------------------------
OPTION ARITHMETIC NATIVE
OPTION BASE 0
SET TEXT background "OPAQUE"
SET POINT STYLE 1
SET AREA COLOR 0
LET DLY=50
DIM St(1,DLY) ,Sy(2000), B4(0,500)
!
LET Kr=0.5
LET Af=1
LET Ei=-70
LET Ss=0.31 ! Ss=(Kr-1)(theta-s(t)) …s(t)=0
LET theta=Ss/(Kr-1)
DEF Ri(Yi,Ss)=Kr*Yi-Af/(1+EXP(Ei*Yi))+Ss
PLOT TEXT,AT .04,.96:"*** Neuro Cell"
PLOT TEXT,AT .04,.92:"Right Click to Stop"
PLOT TEXT,AT .04,.89:"Left Click & Drag '|' Line"
!
!-----
LET Y0=Af/100
LET Af2=Af
DO
LET Af=Af2
CALL ma200_
! ma100_
!----- clear
SET WINDOW -Af*2.07-Af*1.06,Af*2.07-Af*1.06,-Af*2.07-Af*1.05,Af*2.07-Af*1.05
PLOT AREA: -Af,-Af;Af,-Af;Af,Af;-Af,Af
!----- box outline
SET LINE COLOR "blue"
PLOT LINES: -Af,-Af; Af,-Af; Af,Af; -Af,Af; -Af,-Af
!-----
PLOT TEXT,AT Af*.03,Af*.85: "+Af Y(t+1)"
PLOT TEXT,AT -Af*.97,Af*0.13: "Y(t)"
PLOT TEXT,AT -Af*.97, 0: "-Af"
PLOT TEXT,AT Af*.8, 0: "+Af"
PLOT TEXT,AT Af*.03,-Af*.98: "-Af"
!----- Sy(w)=Y(t)
LET imax=pixelx(Af)-pixelx(-Af)
LET dA1=(Af+Af)/imax
FOR i=0 TO imax
LET Sy(i)=Ri(-Af+i*dA1, Ss)
NEXT i
!-----
DO
LET Y1=Ri(Y0,Ss)
!----- erase old signal
LET W0=St(0,t)
LET W1=St(1,t)
FOR i=0 TO DLY-1
IF W0=St(0,i) AND W1=St(1,i) AND t<>i THEN EXIT FOR
NEXT i
IF DLY=i THEN
SET LINE COLOR 0
PLOT LINES: W0,W0; W0,W1;
PLOT LINES: W1,W1
END IF
!----- axis
SET LINE COLOR "cyan" ! axis_Y(t)… ―
PLOT LINES: -Af,0; Af,0
SET LINE COLOR "magenta" ! axis_Y(t+1)…|
PLOT LINES: 0,-Af; 0,Af
!----- draw curve Y(t)
SET LINE COLOR 1
FOR i=0 TO imax
PLOT LINES: -Af+i*dA1, Sy(i);
NEXT i
PLOT LINES
!----- signal
SET LINE COLOR "cyan" ! input_Y(t)…|
PLOT LINES: Y0,Y0; Y0,Y1;
SET LINE COLOR "magenta" ! output_Y(t+1)… ―
PLOT LINES: Y1,Y1
!-----
LET St(0,t)=Y0
LET St(1,t)=Y1
LET t=MOD(t+1,DLY)
LET Y0=Y1
!-----
WAIT DELAY .02
MOUSE POLL x,y,mlb,mrb
LOOP UNTIL mlb=1 OR mrb=1
!
!----- cursor input
IF mlb=1 THEN
SET WINDOW -0.1*Af,Af, -Af*2.1+Af*1.08,Af*2.1+Af*1.08
DO
MOUSE POLL x,y,mlb,mrb
IF 0<=x AND x<=Af THEN
IF y< Af THEN
IF bx4<>pixelx(x) THEN
LET Ss=x
LET theta=Ss/(Kr-1)
CALL
cursor4( bx4,B4)
END IF
ELSEIF x< Af*.43 THEN
IF y< Af*1.4 THEN
ELSEIF y< Af*1.7 THEN
IF
bx3<>pixelx(x) THEN
LET Ei=x*120/(Af*.43)-120
CALL cursor13( bx3, 1.7, 1.4)
END IF
ELSEIF y< Af*2.1 THEN
IF
bx2<>pixelx(x) THEN
LET Kr=x*1/(Af*.43)
LET theta=Ss/(Kr-1)
CALL cursor13( bx2, 2.1, 1.8)
END IF
ELSEIF y< Af*2.5 THEN
IF
bx1<>pixelx(x) THEN
LET Af2=x*2/(Af*.43)+0.5
MAT St=ZER
LET Y0=Af/100
CALL cursor13( bx1, 2.5, 2.2)
END IF
END IF
END IF
END IF
WAIT DELAY .05
LOOP UNTIL mlb=0
END IF
LOOP UNTIL mrb=1
SUB cursor4( bx,B(,))
MAT PLOT CELLS, IN worldx(bx),Af; worldx(bx),-Af: B
LET bx=pixelx(x)
ASK PIXEL ARRAY (x,Af) B
SET LINE COLOR "red"
PLOT LINES: x,-Af; x,Af
PLOT TEXT,AT 0,Af,USING "Kr=#.### :Af=#.### :Ei=####.# :Ss=#.### :theta=####.###": Kr, Af, Ei, Ss, theta
END SUB
SUB cursor13( bx, uy,ly)
SET LINE COLOR 0
PLOT LINES: worldx(bx),Af*uy-dAy; worldx(bx),Af*ly+dAy
LET bx=pixelx(x)
SET LINE COLOR "red"
PLOT LINES: x,Af*uy-dAy; x,Af*ly+dAy
PLOT TEXT,AT 0,Af,USING "Kr=#.### :Af=#.### :Ei=####.# :Ss=#.### :theta=####.###": Kr, Af2, Ei, Ss, theta
END SUB
SUB ma200_
!----- clear
SET WINDOW -0.1*Af,Af, -Af*2.1+Af*1.08,Af*2.1+Af*1.08
PLOT AREA: 0,-Af;Af,-Af;Af,Af;0,Af
!----- box outline
SET LINE COLOR "blue"
PLOT LINES: 0,-Af; Af,-Af; Af,Af; 0,Af; 0,-Af
PLOT LINES: 0,0; Af,0
!-----
PLOT TEXT,AT -.06*Af,.9*Af : "+Af"
PLOT TEXT,AT -.07*Af,-.05*Af : "Y(t)"
PLOT TEXT,AT -.06*Af,-Af : "-Af"
PLOT TEXT,AT Af*.5,-Af*.98: "0 <--- Ss ---> +Af"
!-----
LET dA2=Af/(pixelx(Af)-pixelx(0))
LET dAy=Af/(pixely(Af)-pixely(0))
LET Yt=0 ! Y(t)
FOR j=0 TO Af STEP dA2 ! j= Ss= (Kr-1)*theta
FOR i=0 TO 99
LET Yt=Ri(Yt,j)
PLOT POINTS: j,Yt
NEXT i
NEXT j
!----- setup cursor Ss
LET x=Ss
ASK PIXEL SIZE (x,Af;x,-Af) i,j
MAT B4=ZER(0,j-1)
ASK PIXEL ARRAY (x,Af) B4
LET bx4=pixelx(x)
CALL cursor4( bx4, B4)
!-----
LET x=(Ei+120)*Af*.43/120 !// Ei=x*120/(Af*.43)-120
LET bx3=pixelx(x)
CALL cursor130( bx3, 1.7, 1.4, "Ei")
LET x=Kr*Af*.43 !// Kr=x*1/(Af*.43)
LET bx2=pixelx(x)
CALL cursor130( bx2, 2.1, 1.8, "Kr")
LET x=(Af-0.5)*Af*.43/2 !// Af2=x*2/(Af*.43)+0.5
LET bx1=pixelx(x)
CALL cursor130( bx1, 2.5, 2.2, "Af")
END SUB
SUB cursor130( bx, uy, ly, w$)
PLOT TEXT,AT -.06*Af,Af*(uy-0.2): w$
SET LINE COLOR "blue"
PLOT LINES: 0,Af*uy; Af*.43,Af*uy; Af*.43,Af*ly; 0,Af*ly; 0,Af*uy
CALL cursor13( bx, uy, ly)
END SUB
!
! 漂流するニューラル・ネット(更新)再投稿
!
!----
OPTION ARITHMETIC NATIVE
OPTION BASE 0
SET WINDOW -10,10, 20,0
SET TEXT background "OPAQUE"
!
DIM E(99),R(99),theta(99),F(99)
DIM Y(99),X(99),NetWork(99,99)
DIM P_(1 TO 5, 99),Px(99)
DIM Sum(1 TO 5)
MAT READ P_
! 1)
DATA 1,1,0,0,0,0,0,0,1,1
DATA 1,1,1,0,0,0,0,1,1,1
DATA 0,1,1,1,0,0,1,1,1,0
DATA 0,0,1,1,1,1,1,1,0,0
DATA 0,0,0,1,1,1,0,0,0,0
DATA 0,0,0,0,1,1,1,0,0,0
DATA 0,0,1,1,1,1,1,1,0,0
DATA 0,1,1,1,0,0,1,1,1,0
DATA 1,1,1,0,0,0,0,1,1,1
DATA 1,1,0,0,0,0,0,0,1,1
! 2)
DATA 0,0,0,0,0,1,0,0,0,0
DATA 0,0,0,0,1,1,1,0,0,0
DATA 0,0,0,0,1,1,1,0,0,0
DATA 0,0,0,1,1,1,1,1,0,0
DATA 0,0,0,1,1,0,1,1,0,0
DATA 0,0,1,1,1,0,1,1,1,0
DATA 0,0,1,1,0,0,0,1,1,0
DATA 0,1,1,1,0,0,0,1,1,1
DATA 0,1,1,1,1,1,1,1,1,1
DATA 0,1,1,1,1,1,1,1,1,1
! 3)
DATA 0,0,1,1,1,0,0,0,1,1
DATA 0,1,1,1,1,1,1,1,1,1
DATA 1,1,1,0,1,1,1,1,0,0
DATA 1,1,0,0,0,1,1,0,0,0
DATA 0,0,0,0,0,0,0,0,0,0
DATA 0,0,0,1,1,0,0,0,1,1
DATA 0,0,1,1,1,1,0,1,1,1
DATA 1,1,1,1,1,1,1,1,1,0
DATA 1,1,0,0,0,1,1,1,0,0
DATA 0,0,0,0,0,0,0,0,0,0
! 4)
DATA 0,0,1,0,0,0,0,1,0,0
DATA 0,0,1,1,0,0,1,1,0,0
DATA 0,0,1,1,1,1,1,1,0,0
DATA 0,0,1,1,1,1,1,1,0,0
DATA 0,0,1,1,1,1,1,1,0,0
DATA 0,1,1,1,1,1,1,1,1,0
DATA 1,1,1,1,1,1,1,1,1,1
DATA 0,0,0,1,1,1,1,0,0,0
DATA 0,0,0,0,1,1,1,0,0,0
DATA 0,0,0,0,0,1,0,0,0,0
! 5)
DATA 0,0,0,0,1,1,0,0,0,0
DATA 0,1,1,0,1,1,0,1,1,0
DATA 0,1,0,0,1,1,0,0,1,0
DATA 0,0,0,0,1,1,0,0,0,0
DATA 1,1,1,1,1,1,1,1,1,1
DATA 1,1,1,1,1,1,1,1,1,1
DATA 0,0,0,0,1,1,0,0,0,0
DATA 0,1,1,0,1,1,0,1,1,0
DATA 0,1,1,0,1,1,0,1,1,0
DATA 0,0,0,0,1,1,0,0,0,0
!----- 初期値サンプル1(感で探すのは無理かも。)
! MAT theta=(-1.27)*CON
! LET Af=1.6
! LET Kr=0.92
! LET Kf=0.4
! LET Ei=-10
!
!----- 初期値サンプル2
MAT theta=ZER ! ニューロン不応の固定成分 (しきい値)
LET Af=1 ! ニューロン自身の感度を不応にする負性の自己帰還結合係数 と、
LET Kr=0.95 ! その減衰定数(0< ,< 1)
LET Kf=0.4 ! ニューロンが、他のニューロンから受ける相互結合の減衰定数(0< ,< 1)
LET Ei=-100 ! 2値化関数、S字形 sigmoid() の入力係数
!
!----- 引き金となる相互結合の刺激の作成(無信号からの励起はできない。)
RANDOMIZE !15 !6
DO
LET j=0
FOR i=0 TO 99
LET F(i)=RND-0.5
LET j=j+F(i)
NEXT i
LOOP UNTIL ABS(j)< .002
!
!----- 環境の準備
SET LINE COLOR 2
FOR n_=1 TO 5
LET w=0
!----- サンプル・パターンの表示
FOR j=0 TO 9
FOR i=0 TO 9
IF P_(n_,j*10+i)>0 THEN
DRAW circle WITH SCALE(0.03)*SHIFT(i*.08-9, j*.08+n_+.9)
LET w=w+1
END IF
NEXT i
NEXT j
PLOT TEXT,AT -6,n_+1.5:"Dots/Body="&STR$(w)&"/100"
PLOT TEXT,AT -8,n_+1.5:":"&STR$(Sum(n_))
LET DC=w/100 ! 平均値(直流成分)
!-----
! 5つのパターンの平均値からの偏差(交流成分)を、
! 1つの行列 NetWork(,) の中に、埋め込む。相互結合係数の行列 作成。
!
! 5 (p) _ (p) _
! 共分散行列の作成 ωij=Σ(χi-χ)*(χj-χ) …参照。
! p=1
!-----
FOR i=0 TO 99
FOR j=0 TO 99
LET NetWork(i,j)=NetWork(i,j)+(P_(n_,i)-DC)*(P_(n_,j)-DC)
NEXT j
NEXT i
NEXT n_
!-----
! 5つが、自己の共分散の形で合算され、1つなった行列 NetWork(,) で、
! 100個のニューロンを接続し、漂流させると・・・
!
! ( 周期の無い計算ですが、演算桁の制限による丸めのために、周期的
! 動作へ落ちています・・長々と、漂着しないときは、Run しなおす。)
!
!-----
PLOT TEXT,AT -9, 1:"漂流するニューラル・ネット"
PLOT TEXT,AT -9, 9:"右クリックで 終了"
PLOT TEXT,AT -9,10:"左クリック STOP/START"
SET LINE COLOR 1
DO
DO
LET T=T+1
PLOT TEXT,AT -9,8:"t="&STR$(T)
CALL DispX
CALL Compare
CALL Xi00
MOUSE POLL mx,my,mlb,mrb
WAIT DELAY 0
LOOP UNTIL mlb=1 OR mrb=1
!----- left click stop/start
IF mlb=1 THEN
DO
WAIT DELAY 0.02
MOUSE POLL mx,my,mlb,mrb
LOOP UNTIL mlb=0
DO
WAIT DELAY 0.02
MOUSE POLL mx,my,mlb,mrb
LOOP UNTIL mlb=1 OR mrb=1
WAIT DELAY 0.1
END IF
!----- right click stop end.
LOOP UNTIL mrb=1
!----- 各ニューロン0~99 の駆動
SUB Xi00
FOR i=0 TO 99
LET w=0
FOR j=0 TO 99
LET w=w+NetWork(i,j)*X(j)
NEXT j
LET F(i)=Kf*F(i)+w
LET R(i)=Kr*(R(i)+theta(i))-Af*X(i)-theta(i)
LET Y(i)=R(i)+F(i)
NEXT i
FOR i=0 TO 99
IF Ei*Y(i)< 709 THEN ! 桁あふれ防止
LET X(i)=1/(1+EXP(Ei*Y(i)))
ELSE
LET X(i)=1/(1+EXP(709))
END IF
NEXT i
END SUB
!----- 各ニューロンの出力 X(0~99) 発火の、画面表示。
SUB DispX
SET DRAW mode hidden
SET AREA COLOR 0
PLOT AREA:-10,10; 0,10; 0,0; 10,0; 10,20;-10,20
SET AREA COLOR 2 ! //fire
FOR V=0 TO 9
FOR H=0 TO 9
LET i=V*10+H
IF 0.5=< X(i) THEN
PLOT AREA: H,V; H+1,V; H+1,V+1; H,V+1
LET Px(i)=1
SET COLOR MIX(0) 0,1,1 ! B.G.color cyan( text)
ELSE
PLOT LINES: H,V; H,V+1; H+1,V+1
LET Px(i)=0
SET COLOR MIX(0) 1,1,1 ! B.G.color 0
END IF
!----- ニューロンの内部(-~0~+) 0=< は発火
PLOT TEXT,AT H*2-10, V*0.8+12, USING"###.###":Y(i)
NEXT H
NEXT V
SET COLOR MIX(0) 1,1,1 ! B.G.color 0
SET DRAW mode explicit
END SUB
!----- 生成パターンの分別 計数の、画面表示。
SUB Compare
FOR n_=1 TO 5
FOR i=0 TO 99
IF P_(n_,i)<>Px(i) THEN EXIT FOR
NEXT i
IF 99< i THEN
! ----- 一致
LET PC_=10 ! //timer ON 1st.to 2nd.Cursor
IF PB_=n_ THEN EXIT SUB
IF PN_>0 THEN PLOT
TEXT,AT -8, PN_+1.5: ":"& STR$(Sum(PN_))& " " ! //old
1st.2nd.Cursor OFF
LET PB_=n_ ! //flag 2nd.Cursor
LET PN_=n_ ! //flag 1st.Cursor
LET Sum(n_)=Sum(n_)+1 ! 計数
SET COLOR MIX(0) 0,1,1 ! //new 1st.Cursor ON (B.G.color)
PLOT label,AT -8, n_+1.5: ":"& STR$(Sum(n_))& " "
SET COLOR MIX(0) 1,1,1
beep
EXIT SUB
!-----
END IF
NEXT n_
! ----- 不一致
IF PB_=0 THEN EXIT SUB
IF PC_>1 THEN
LET PC_=PC_-1
EXIT SUB
END IF
SET COLOR MIX(0) .75,.75,.75 ! //new 2nd.Cursor ON (B.G.color)
PLOT TEXT,AT -8, PB_+1.5: ":"& STR$(Sum(PB_))& " "
SET COLOR MIX(0) 1,1,1
LET PB_=0
END SUB
100 INPUT PROMPT "p=": P
110 INPUT PROMPT "q=": Q
120 INPUT PROMPT "d=": D
130 LET U=0
140 FOR K=1 TO D !d以下の自然数kのうちで
150 IF K-INT(K/P)*P=0 THEN GOTO 210 !kがpの倍数の場合(k=m*p+0) ※MOD(K,P)=0
160 FOR M=0 TO INT(K/P) !0からPで割った商まで ∵k=m*p+r
170 LET R=K-M*P !k-m*p=n*q
180 IF R-INT(R/Q)*Q=0 THEN GOTO 210 !rがqの倍数の場合 ※MOD(R,Q)=0
190 NEXT M
200 GOTO 230 !該当なし。次へ
210 PRINT K !条件を満たす
220 LET U=U+1
230 NEXT K
240 PRINT "総数="; U
250 END
100 INPUT PROMPT "p=": P
110 INPUT PROMPT "q=": Q
120 INPUT PROMPT "d=": D
130 LET U=0
140 FOR K=1 TO D !d以下の自然数kのうちで
150 !
160 FOR M=0 TO INT(K/P) !0からKをPで割った商まで
170 LET R=K-M*P !k-m*p=n*q
180 IF R-INT(R/Q)*Q=0 THEN GOTO 210 !rがqの倍数の場合 ※MOD(R,Q)=0
190 NEXT M
200 GOTO 230 !該当なし。次へ
210 PRINT K; M;INT(R/Q) !条件を満たすM,N ※
220 LET U=U+1
230 NEXT K
240 PRINT "総数="; U
250 END
*アルゴリズムの数学的背景
不定方程式 k=m*p+n*q は、k-m*p=n*q と変形される。
合同式で表すと、k-m*p≡0 mod q となる。
m は0以上の整数、p は自然数より、m*p≧0 となる。 同様に、n*q≧0。
また、n*q=k-m*p≧0 より、k≧m*p となる。
したがって解があれば、mは0〜INT(K/P)で見つかる。
●(m,n)の組は一通りでない。その組を調べる。
・180行目を変更と追加(210,220行目)
・150,200,210,220行目を削除
100 INPUT PROMPT "p=": P
110 INPUT PROMPT "q=": Q
120 INPUT PROMPT "d=": D
130 LET U=0
140 FOR K=1 TO D !d以下の自然数kのうちで
150 !
160 FOR M=0 TO INT(K/P) !0からKをPで割った商まで
170 LET R=K-M*P !k-m*p=n*q
180 IF R-INT(R/Q)*Q=0 THEN !rがqの倍数の場合 ※MOD(R,Q)=0
PRINT K; M;INT(R/Q) !条件を満たすM,N
LET U=U+1
END IF
190 NEXT M
200 !
210 !
220 !
230 NEXT K
240 PRINT "総数="; U !※意味が変わる
250 END
Full BASICの場合、行列が計算できるので、他の言語よりは簡単に計算できると思います。
ただ、2項演算までですから、展開しながらこつこつ計算する必要があります。
また、表計算の方がGUIを含めて実用化し易いかもしれません。
上記サイトの例題(PDFファイル内)のサンプルコーディング
!最小2乗法による測量網平均(条件方程式法)
!H型
! A C
! 1↓ 5 ↓3
! P → Q
! 2↑ ↑4
! B D
!既知点
LET C=4 !数
DATA 25.645 !A点の標高(m)
DATA 24.666 !B点
DATA 25.024 !C点
DATA 25.699 !D点
DIM Z(C)
MAT READ Z
!観測値
LET P=5 !数
DATA -6.225, 0.44 !路線1 高低差(m)、路線長(km)
DATA -5.245, 0.25 !路線2
DATA 0.278, 0.33 !路線3
DATA -0.399, 0.26 !路線4
DATA 5.879, 0.44 !路線5
DIM X(P),G(P,P) !観測値、コアファクタ
MAT G=ZER
FOR i=1 TO P
READ X(i),G(i,i)
NEXT i
MAT PRINT X;
MAT PRINT G;
!未知数
LET Px=2 !求点PとQ
!------------------------------
!自由度R ※条件方程式の数
LET R=P-Px
!条件方程式 UV=t
DIM U(R,P)
DATA 1,-1,0,0,0 !点Pについて HA+h1~=HB+h2~ より、(h1+v1)-(h2+v2)=HB-HA ∴v1-v2=-(h1+HA)+(h2+HB)
DATA 0,0,1,-1,0 !点Qについて HC+h3~=HD+h4~
DATA 1,0,0,-1,1 !点Pと点Qについて HA+h1~+h5~=HD+h4~
MAT READ U
DIM t(R,1)
FOR i=1 TO R
LET s=0
FOR j=1 TO P
IF j>C THEN LET Zj=0 ELSE LET Zj=Z(j)
LET s=s-(X(j)+Zj)*U(i,j)
NEXT j
LET t(i,1)=s
NEXT i
!!!LET t(1,1)=-X(1)+X(2)-Z(1)+Z(2) !0.001
!!!LET t(2,1)=-X(3)+X(4)-Z(3)+Z(4) !-0.002
!!!LET t(3,1)=-X(1)+X(4)-X(5)-Z(1)+Z(4) !0.001
MAT PRINT t;
!------------------------------
!相関式 NK=t、N=UG(Ut)より、K=(Ni)tを求める
DIM Ut(P,R)
MAT Ut=TRN(U)
DIM TMP(P,R) !G(Ut) ※次でも使う
MAT TMP=G*Ut
DIM N(R,R)
MAT N=U*TMP
MAT PRINT N;
DIM invN(R,R)
MAT invN=INV(N)
DIM K(R,1)
MAT K=invN*t
MAT PRINT K;
!補正値の計算(mm) V=G(Ut)K
DIM V(P,1)
MAT V=TMP*K
MAT PRINT V;
!最確値 X~=X+V
FOR i=1 TO P
PRINT "路線";STR$(i);"=";X(i)+V(i,1)
NEXT i
PRINT "点P";Z(1)+(X(1)+V(1,1)); Z(2)+(X(2)+V(2,1)) !有効桁数 ##.###
PRINT "点Q";Z(3)+(X(3)+V(3,1)); Z(4)+(X(4)+V(4,1))
!精度の計算(mm^2) σ^2=(Kt)NK/r
DIM s2(1,1),Kt(1,R)
MAT Kt=TRN(K)
MAT s2=Kt*t !NK=t
LET sigma2=s2(1,1)/R
PRINT "σ^2=";sigma2
!分散行列(mm^2) σ^2*Gx、Gx=G-G(Ut)(Ni)UG
DIM Gx(P,P)
MAT Gx=TMP*invN !G(Ut)(Ni)
MAT Gx=Gx*U
MAT Gx=Gx*G
MAT Gx=G-Gx
MAT Gx=sigma2*Gx
MAT PRINT Gx;
END
1000 !節点電位法によるフィルタ回路の周波数解析(利得、位相)
1010
1020 OPTION ARITHMETIC COMPLEX
1030
1040 LET j=SQR(-1) !虚数単位 ※電気系はjを使う
1050
1060 LET f=60 !周波数[Hz]
1070 DEF w=2*PI*f !角周波数ω
1080
1090 DEF H2Ohm(L)=j*w*L ![H]を[Ω]へ
1100 DEF F2Ohm(C)=1/(j*w*C) ![F]を[Ω]へ
1110 DEF xL(L)=w*L !誘導リアクタンス
1120 DEF xC(C)=1/(w*C) !容量リアクタンス
1130
1140 SUB DispS(z) !複素数をS表示する ※スタインメッツ(Steinmetz)
1150 PRINT ABS(z);
1160 IF ABS(z)<>0 THEN
1170 IF arg(z)<>0 THEN PRINT "∠";DEG(arg(z));"°";
1180 END IF
1190 !PRINT
1200 END SUB
1210
1220 FUNCTION S2COMPLEX(l,th) !S表示(極座標形式)を複素数へ
1230 LET S2COMPLEX=COMPLEX(l*COS(RAD(th)),l*SIN(RAD(th)))
1240 END FUNCTION
1250 FUNCTION i2COMPLEX(im,th) !瞬時値式を複素数へ ※最大値、初期位相
1260 LET i2COMPLEX=S2COMPLEX(im/SQR(2),th) !実効値、初期位相
1270 END FUNCTION
1280 !-------------------- ここまでがサブルーチン
1290
1300
1310 SUB set_curcit !素子や結線を定義する
1320 !---------- ↓↓↓↓↓ ----------
1330
1340 !●回路図 Sallen-Key 3次ローパス・フィルタ
1350
1360 !参考サイト http://sim.okawa-denshi.jp/OPseikiLowkeisan.htm
1370
1380 ! ┌─C2─┬──────┐
1390 ! │ │ ┌──┐ │
1400 ! │ └─┤- │ │
1410 ! │ │ K├─6─
1420 ! ─2─R1─3─R2─4─R3─5─┤+ │ ↑
1430 ! ↑ │ │ └──┘ │
1440 ! Vi C1 C3 Vo
1450 ! ↓ │ │ ↓
1460 ! ─1───┴───────┴──────┴─
1470 ! │
1480 ! ≡アース
1490
1500 LET GND=1 !アース
1510 LET Vi=2 !入力端子
1520 LET Vo=6 !出力端子
1530
1540 !素子: Rn,Vn,In、n:番号(連番) ※2文字目以降は番号
1550 !値:
1560 !端子番号(起点): 1以上の値 ※節点
1570 !端子番号: 1以上の値 ※節点
1580
1590 CALL AddElements("R1",51e3,2,3) !51k[Ω]、枝路電流は2→3と仮定する
1600 CALL AddElements("C1",F2Ohm(0.0068e-6),3,1) !0.0068[μF]
1610 CALL AddElements("R2",82e3,3,4) !82k[Ω]
1620 CALL AddElements("C2",F2Ohm(0.022e-6),4,6) !0.022[μF]
1630 CALL AddElements("R3",39e3,4,5) !39k[Ω]
1640 CALL AddElements("C3",F2Ohm(330e-12),5,1) !330[pF]
1650
1660 !※電圧源の番号は1からの連番 例. CALL AddElements("V1",?,?,?) !?[V]
1670 !なし
1680
1690 CALL AddElements("A1",1.0,5,6) !アンプ 増幅率1.0,+端子5,出力端子6
1700
1710 !---------- ↑↑↑↑↑ ----------
1720
1730 CALL AddElements("Vi",10,GND,Vi) !10[V] ※測定用の電圧
1740 END SUB
1750
1760 !---------- ↓↓↓↓↓ ----------
1770 LET Ns=0 !電圧源の数
1780 LET Nd=6 !節点の数
1790 LET Na=1 !アンプの数
1800 !---------- ↑↑↑↑↑ ----------
1810
1820 LET N=Nd+Ns+Na+1
1830
1840 !●キルヒホッフの電流則より、節点方程式を組み立てる
1850 DIM A(N,N),x(N),b(N) !連立方程式 Ax=b
1860
1870 DIM AmpK(Na),AmpPlus(Na),AmpOut(Na)
1880
1890 SUB AddElements(el$,ev,nd1,nd2) !結線情報から回路方程式を組み立てる
1900 IF (nd1<1 OR nd1>Nd) OR (nd2<1 OR nd2>Nd) THEN
1910 PRINT "素子";el$;"の節点番号が違います。";nd1;nd2
1920 STOP
1930 END IF
1940
1950 !連立方程式を組み立てる Ax=b
1960 ! ┌ │ ┐┌ ┐ ┌ ┐
1970 ! │G │±1││V │=│I │ R,C,L,電流源(Nd個)
1980 !───┼─────────
1990 ! │±1│-Zp││Ip│ │Ep│ 電圧源(Ns個)、アンプ(Na個)、入力電圧源(1個)
2000 ! └ │ ┘└ ┘ └ ┘
2010
2020 SELECT CASE UCASE$(el$(1:1)) !素子に応じて
2030 CASE "V" !電圧源なら
2040 LET t$=UCASE$(el$(2:LEN(el$)))
2050 IF t$="I" THEN !計測用の入力電圧源なら
2060 LET p=Nd+Ns+Na+1
2070 ELSE
2080 LET p=VAL(t$) !番号を得る
2090 IF p<1 OR p>Ns THEN
2100 PRINT "電圧源の番号が違います。";el$
2110 STOP
2120 END IF
2130 LET p=p+Nd
2140 END IF
2150 LET A(nd1,p)=A(nd1,p)-1 !電流Ipが節点iから節点jへ流れたとして、(Vi-Vj)-Ip*Zp=Ep
2160 LET A(p,nd1)=A(p,nd1)-1
2170 LET A(nd2,p)=A(nd2,p)+1
2180 LET A(p,nd2)=A(p,nd2)+1
2190 LET A(p,p)=A(p,p)+0 !内部抵抗Zpは0とする
2200 LET b(p)=b(p)+ev !起電力
2210
2220 CASE "A" !アンプなら
2230 LET t=VAL(el$(2:LEN(el$))) !番号を得る
2240 IF t<1 OR t>Na THEN
2250 PRINT "アンプの番号が違います。";el$
2260 STOP
2270 END IF
2280 LET p=t+Nd+Ns !出力側をノレータ(初期値0Vの電圧源)として扱う
2290 LET A(GND,p)=A(GND,p)-1
2300 LET A(p,GND)=A(p,GND)-1
2310 LET A(nd2,p)=A(nd2,p)+1
2320 LET A(p,nd2)=A(p,nd2)+1
2330
2340 LET AmpK(t)=ev !増幅率
2350 LET AmpPlus(t)=nd1 !+端子
2360 LET AmpOut(t)=p !方程式内での出力端子
2370
2380 CASE "I" !電流源なら
2390 LET b(nd1)=b(nd1)-ev
2400 LET b(nd2)=b(nd2)+ev
2410
2420 CASE ELSE !素子なら
2430 LET Gij=1/ev
2440 !対角成分 ※節点に接続された素子(アドミタンス)の和
2450 LET A(nd1,nd1)=A(nd1,nd1)+Gij
2460 LET A(nd2,nd2)=A(nd2,nd2)+Gij
2470 !その他の成分 ※節点に接続された素子(アドミタンス)に-1をかけたものの和
2480 LET A(nd1,nd2)=A(nd1,nd2)-Gij
2490 LET A(nd2,nd1)=A(nd2,nd1)-Gij
2500
2510 END SELECT
2520 END SUB
2530
2540 DIM Ai(N,N) !連立方程式を解く
2550 SUB routine
2560 MAT A=ZER
2570 MAT b=ZER
2580 CALL set_curcit !結線から方程式を組み立てる
2590
2600 FOR i=1 TO Nd !結線されていない節点 1*Vi=0
2610 IF A(i,i)=0 THEN LET A(i,i)=1
2620 NEXT i
2630 LET A(GND,GND)=0 !電位を0とする
2640
2650 !!!MAT PRINT A; !dump it
2660 !!!MAT PRINT b;
2670
2680
2690 MAT Ai=INV(A)
2700 MAT x=Ai*b
2710 IF Na>0 THEN !アンプがあれば
2720 FOR iter=1 TO 100 !安定させる ※要調整
2730 FOR i=1 TO Na
2740 LET b(AmpOut(i))=AmpK(i)*x(AmpPlus(i)) !Vo=K*V+ ※入力を出力に反映させる
2750 NEXT i
2760 MAT x=Ai*b
2770 NEXT iter
2780 END IF
2790 END SUB
2800
2810
2820
2830 !SET bitmap SIZE 600,600 !画面を大きくする
2840 LET ymin=-150
2850 SET WINDOW -0.5,6.5, ymin,5 !表示領域
2860 DRAW grid(1,5) !左端の目盛り
2870
2880 FOR f=1 TO 6 !x軸が対数
2890 PLOT TEXT ,AT f-0.3,-0.15: mid$("10 100 1k 10k 100k1M ",4*(f-1)+1,4)
2900 NEXT f
2910
2920 FOR f=10 TO 100000 STEP 100 !周波数[Hz]
2930 CALL routine
2940 PLOT LINES: LOG10(f),20*LOG10(ABS(x(Vo)/x(Vi))); !利得[dB]
2950 NEXT f
2960 PLOT LINES
2970
2980
2990 SET TEXT COLOR 2
3000 FOR i=5 TO ymin STEP -5 !右端の縦軸目盛り
3010 PLOT TEXT ,AT 6,i: STR$(i*2)&"°" !※利得のグラフに合わせるために2倍する
3020 NEXT i
3030
3040 SET LINE COLOR 2
3050 FOR f=10 TO 100000 STEP 100 !周波数[Hz]
3060 CALL routine
3070 LET t=arg(x(Vo)/x(Vi))
3080 IF t>0 THEN LET t=t-2*PI !0〜-2πへ補正する
3090 PLOT LINES: LOG10(f),DEG(t)/2; !位相θ ※利得のグラフに合わせるために1/2倍する
3100 NEXT f
3110 PLOT LINES
3120
3130
3140 END
REM *** 逆行列で高速マクローリン展開
DIM a(3,3),b(3,1),c(3,1),d(3,3)
DEF f(x)=EXP(x)
LET x=0.0001
LET a(1,1)=x
LET a(1,2)=x^2
LET a(1,3)=x^3
LET a(2,1)=2*x
LET a(2,2)=4*x^2
LET a(2,3)=8*x^3
LET a(3,1)=3*x
LET a(3,2)=9*x^2
LET a(3,3)=27*x^3
MAT d=INV(a)
LET e=f(0)
LET c(1,1)=f(x)-e
LET c(2,1)=f(2*x)-e
LET c(3,1)=f(3*x)-e
MAT b=d*c
PRINT b(1,1)
PRINT b(2,1)
PRINT b(3,1)
END
2710 IF Na>0 THEN !アンプがあれば
2720 FOR iter=1 TO 1 !安定させる ※要調整 <---------- ここ
2730 FOR i=1 TO Na
2740 LET b(AmpOut(i))=AmpK(i)*x(AmpPlus(i)) !Vo=K*V+ ※入力を出力に反映させる
2750 NEXT i
2760 MAT x=Ai*b
2770 NEXT iter
2780 END IF
10 OPTION ARITHMETIC COMPLEX
LET j=SQR(-1)
OPTION BASE 1
OPTION ANGLE DEGREES
DIM FREQ(100,5)
LET FREQ(1,1)=10
LET FREQ(2,1)=12.25
LET FREQ(3,1)=15
LET FREQ(4,1)=17.32
LET FREQ(5,1)=20
LET FREQ(6,1)=24.5
LET FREQ(7,1)=30
LET FREQ(8,1)=34.6
LET FREQ(9,1)=40
LET FREQ(10,1)=50
LET FREQ(11,1)=60
LET FREQ(12,1)=70
LET FREQ(13,1)=80
LET FREQ(14,1)=90
FOR I=1 TO 14
LET P=I
LET FREQ(I,1)=FREQ(P,1)
NEXT I
FOR I=15 TO 28
LET P=I-14
LET FREQ(I,1)=FREQ(P,1)*10
NEXT I
FOR I=29 TO 42
LET P=I-28
LET FREQ(I,1)=FREQ(P,1)*100
NEXT I
FOR I=43 TO 56
LET P=I-42
LET FREQ(I,1)=FREQ(P,1)*1000
NEXT I
LET FREQ(57,1)=100000
! FOR I=1 TO 57
! PRINT "FREQ(";I;",1)=";FREQ(I,1)
! NEXT I
20 ! CR 3段回路
LET FF=1000 !Fの単位はヘルツ
LET R1=51000 !Rの単位はオーム
LET R2=82000
LET R3=39000
LET C1=0.00685/(10^6) !Cの単位はuF,
LET C2=0.022/(10^6) !Cの単位はuF,
LET C3=330/(10^12) !Cの単位はPF,
LET Y1=(2*PI*FF*C1) !Yの単位はモー
LET Y2=(2*PI*FF*C2)
LET Y3=(2*PI*FF*C3)
LET ω=(2*PI*FF)
LET Rs=0.1 !Rsの単位はオーム �,肇◆璽垢貌�れる。
LET IS=10 !Isの単位はアムペア Rsに加わる電流源で�,肇◆璽垢�1Vにする。
FOR K=0.9875 TO 1.0125 STEP 0.0125 !KはAMPのゲイン。
FOR P=1 TO 57
LET FF=FREQ(P,1)
LET ω=(2*PI*FF)
LET
A(1,1)=(1/Rs)+(1/R1)
!�´|嫉劼離▲疋潺織鵐垢旅膩�
LET
A(1,2)=-(1/R1)
!�´�端子のアドミタンスの -1
LET A(1,3)=0
LET A(1,4)=0
LET A(2,1)=-(1/R1)
LET A(2,2)=(1/R1)+(1/R2)+ω*C1*j !�↓�端子のアドミタンスの合計
LET A(2,3)=-(1/R2)
LET A(2,4)=0
LET A(3,1)=0
LET A(3,2)=-(1/R2)
LET A(3,3)=(1/R2)+(1/R3)+ω*C2*j !���C嫉劼離▲疋潺織鵐垢旅膩�
LET A(3,4)=-(1/R3)-K*ω*C2*j !ここにKの値を入れ V5=K*V4 を反映。
!ミルマンの定理を適用。
LET A(4,1)=0
LET A(4,2)=0
LET
A(4,3)=-(1/R3) !A(3,4)とは値が異なる。
LET
A(4,4)=(1/R3)+ω*C3*j
!�きっ嫉劼離▲疋潺織鵐垢旅膩�
LET B(1,1)=10 ! 電流源から10Aを流している。�|嫉劼�1Vになる。
LET B(2,1)=0 ! キルヒホッフの法則から ゼロである。
LET B(3,1)=0 ! キルヒホッフの法則から ゼロである。
LET B(4,1)=0 ! キルヒホッフの法則から ゼロである。
MAT T=INV(A)
MAT EOUT=T*B
! PRINT "FF=";FF
! MAT PRINT EOUT
LET EE1=EOUT(1,1)
LET EE2=EOUT(2,1)
LET EE3=EOUT(3,1)
LET EE4=EOUT(4,1)
LET EE5=K*EOUT(4,1)
PRINT
LET FREQ(P,2)=20*LOG10(ABS(EE5))
! LET FREQ(P,3)=20*LOG10(ABS(EE3))
LET G5=(ATN(IM(EE5)/RE(EE5)))
IF FF>750 THEN LET G5=G5-180
IF G5>0 THEN LET G5=G5-180
LET FREQ(P,4)=G5
! LET G3=(ATN(IM(EE3)/RE(EE3)))
! IF FF>750 THEN LET G3=G3-180
! LET FREQ(P,5)=G3
NEXT P
PRINT "K=";K
PRINT "番号
周波
数 E5
E3
θ5 θ3"
FOR I=1 TO 57
PRINT USING "###": I;
PRINT USING " ###,###.#" : FREQ(I,1);
PRINT USING " ####.### dB": FREQ(I,2);
PRINT USING " ####.### dB": FREQ(I,3);
PRINT USING " ####.### 度": FREQ(I,4);
PRINT USING " ####.### 度": FREQ(I,5)
NEXT I
!ここからは、山中様のグラフプログラムを参照。
SET WINDOW 0.5,5.5, -55,5 !表示領域
DRAW
grid(1,5) !
左端の目盛り
FOR f=1 TO 6 !x軸が対数目盛 f=1 TO 5 で100k まで目盛る。
SET COLOR 1 !1は黒色
PLOT TEXT ,AT f-0.1,+0.15: mid$("10 100 1k 10k 100k ",4*(f-1)+1,4)
NEXT f
FOR f=1 TO 6 !y軸が直線目盛り
SET COLOR 1 !1は黒色
PLOT TEXT ,AT 0.8,-10*(f-1)-2: mid$(" 0 -25 -50 -75 -100-125 ",4*(f-1)+1,4)
NEXT f
FOR I=1 TO 57 STEP 1 !周波数[Hz]
SET COLOR 1
PLOT LINES:LOG10(FREQ(I,1)) ,FREQ(I,2)/2.5; !利得[dB]
NEXT I
PLOT LINES
! FOR I=1 TO 57 STEP 1 !周波数[Hz]
! SET COLOR 5 !5は水色
! PLOT LINES: LOG10(FREQ(I,1)) ,FREQ(I,3)/2; !利得[dB]
! NEXT I
! PLOT LINES
FOR I=1 TO 57 STEP 1 !位相角度[度]
SET COLOR 4 !4は赤色
PLOT LINES:LOG10(FREQ(I,1)) ,0.125*FREQ(I,4); !角度[度]
NEXT I
PLOT LINES
! FOR I=1 TO 57 STEP 1 !位相角度[度]
! SET COLOR 3 !3は緑色
! PLOT LINES:LOG10(FREQ(I,1)) ,0.25*FREQ(I,5); !角度[度]
! NEXT I
! PLOT LINES
FOR f=1 TO 6 !y軸が直線目盛り
SET COLOR 4
PLOT TEXT ,AT 5.1,-10*(f-1)-2: mid$(" 0 -80 -160-240-320-400 ",4*(f-1)+1,4)
NEXT f
PRINT
NEXT K ! ここで,利得 Kを変化させる。
!*******************************************************************
!100 LET FF=1000
! PRINT 1/R1
! PRINT 1/R2
! PRINT 1/R3
! PRINT Y1
! PRINT Y2
! PRINT Y3
! FOR I=1 TO NP ! 白石様の御助言を参照。マトリクスのチェックをした。
! FOR J=1 TO NP
! LET Z=A(I,J)
! PRINT USING "(##.######### ":RE(Z);
! PRINT USING "##.#########) ":IM(Z);
! NEXT J
! PRINT
! NEXT I
!**********************************************************************
10 OPTION ARITHMETIC COMPLEX
LET j=SQR(-1)
OPTION BASE 1
OPTION ANGLE DEGREES
DIM FREQ(100,5)
LET FREQ(1,1)=10
LET FREQ(2,1)=12.25
LET FREQ(3,1)=15
LET FREQ(4,1)=17.32
LET FREQ(5,1)=20
LET FREQ(6,1)=24.5
LET FREQ(7,1)=30
LET FREQ(8,1)=34.6
LET FREQ(9,1)=40
LET FREQ(10,1)=50
LET FREQ(11,1)=60
LET FREQ(12,1)=70
LET FREQ(13,1)=80
LET FREQ(14,1)=90
FOR I=1 TO 14
LET P=I
LET FREQ(I,1)=FREQ(P,1)
NEXT I
FOR I=15 TO 28
LET P=I-14
LET FREQ(I,1)=FREQ(P,1)*10
NEXT I
FOR I=29 TO 42
LET P=I-28
LET FREQ(I,1)=FREQ(P,1)*100
NEXT I
FOR I=43 TO 56
LET P=I-42
LET FREQ(I,1)=FREQ(P,1)*1000
NEXT I
LET FREQ(57,1)=100000
! FOR I=1 TO 57
! PRINT "FREQ(";I;",1)=";FREQ(I,1)
! NEXT I
20 ! CR 3段回路
LET FF=1000 !Fの単位はヘルツ
LET R1=51000 !Rの単位はオーム
LET R2=82000
LET R3=39000
LET C1=0.00685/(10^6) !Cの単位はuF,
LET C2=0.022/(10^6) !Cの単位はuF,
LET C3=330/(10^12) !Cの単位はPF,
LET Y1=(2*PI*FF*C1) !Yの単位はモー
LET Y2=(2*PI*FF*C2)
LET Y3=(2*PI*FF*C3)
LET ω=(2*PI*FF)
LET Rs=0.1 !Rsの単位はオーム �,肇◆璽垢貌�れる。
LET IS=10 !Isの単位はアムペア Rsを1Vにする。
FOR K=0.9875 TO 1.0125 STEP 0.0125 !KはAMPのゲイン。
FOR P=1 TO 57
LET FF=FREQ(P,1)
LET ω=(2*PI*FF)
LET A(1,1)=(1/Rs)+(1/R1) !�´|嫉劼離▲疋潺織鵐垢旅膩�
LET
A(1,2)=-(1/R1)
!�´�端子のアドミタンスの -1
LET A(1,3)=0
LET A(1,4)=0
LET A(1,5)=0
LET A(2,1)=-(1/R1)
LET A(2,2)=(1/R1)+(1/R2)+ω*C1*j !�↓�端子のアドミタンスの合計
LET A(2,3)=-(1/R2)
LET A(2,4)=0
LET A(2,5)=0
LET A(3,1)=0
LET A(3,2)=-(1/R2)
LET A(3,3)=(1/R2)+(1/R3)+ω*C2*j!���C嫉劼離▲疋潺織鵐垢旅膩�
LET A(3,4)=-(1/R3) !A(4,3)と値が同じくし対称行列にする。
LET A(3,5)=-ω*C2*j
LET A(4,1)=0
LET A(4,2)=0
LET A(4,3)=-(1/R3) !A(3,4)と値が同じくし対称行列にする。
LET A(4,4)=(1/R3)+ω*C3*j !�きっ嫉劼離▲疋潺織鵐垢旅膩�
LET A(4,5)=0
LET A(5,1)=0
LET A(5,2)=0
LET A(5,3)=0
LET A(5,4)=-K ! ここにKの値を入れ V5=K*V4 を反映。
LET A(5,5)=1 ! ここに1の値を入れ V5=K*V4 を反映。
LET B(1,1)=10 ! 電流源から10Aを流す。�|嫉劼�1V。
LET B(2,1)=0 ! キルヒホッフの法則から ゼロである。
LET B(3,1)=0 ! キルヒホッフの法則から ゼロである。
LET B(4,1)=0 ! キルヒホッフの法則から ゼロである。
LET B(5,1)=0 ! ここに0の値を入れ V5=K*V4 を反映。
MAT T=INV(A)
MAT EOUT=T*B
! PRINT "FF=";FF
! MAT PRINT EOUT
LET EE1=EOUT(1,1)
LET EE2=EOUT(2,1)
LET EE3=EOUT(3,1)
LET EE4=EOUT(4,1)
LET EE5=EOUT(5,1)
PRINT
LET FREQ(P,2)=20*LOG10(ABS(EE5))
! LET FREQ(P,3)=20*LOG10(ABS(EE3))
LET G5=(ATN(IM(EE5)/RE(EE5)))
IF FF>750 THEN LET G5=G5-180
IF G5>0 THEN LET G5=G5-180
LET FREQ(P,4)=G5
! LET G3=(ATN(IM(EE3)/RE(EE3)))
! IF FF>750 THEN LET G3=G3-180
! LET FREQ(P,5)=G3
NEXT P
PRINT "K=";K
PRINT "番号
周波
数 E5
E3
θ5 θ3"
FOR I=1 TO 57
PRINT USING "###": I;
PRINT USING " ###,###.#" : FREQ(I,1);
PRINT USING " ####.### dB": FREQ(I,2);
PRINT USING " ####.### dB": FREQ(I,3);
PRINT USING " ####.### 度": FREQ(I,4);
PRINT USING " ####.### 度": FREQ(I,5)
NEXT I
!ここからは、山中様のグラフプログラムを参照。
SET WINDOW 0.5,5.5, -55,5 !表示領域
DRAW
grid(1,5) !
左端の目盛り
FOR f=1 TO 6 !x軸が対数目盛 f=1 TO 5 で100k まで目盛る。
SET COLOR 1 !1は黒色
PLOT TEXT ,AT f-0.1,+0.15: mid$("10 100 1k 10k 100k ",4*(f-1)+1,4)
NEXT f
FOR f=1 TO 6 !y軸が直線目盛り
SET COLOR 1 !1は黒色
PLOT TEXT ,AT 0.8,-10*(f-1)-2: mid$(" 0 -25 -50 -75 -100-125 ",4*(f-1)+1,4)
NEXT f
FOR I=1 TO 57 STEP 1 !周波数[Hz]
SET COLOR 1
PLOT LINES:LOG10(FREQ(I,1)) ,FREQ(I,2)/2.5; !利得[dB]
NEXT I
PLOT LINES
! FOR I=1 TO 57 STEP 1 !周波数[Hz]
! SET COLOR 5 !5は水色
! PLOT LINES: LOG10(FREQ(I,1)) ,FREQ(I,3)/2; !利得[dB]
! NEXT I
! PLOT LINES
FOR I=1 TO 57 STEP 1 !位相角度[度]
SET COLOR 4 !4は赤色
PLOT LINES:LOG10(FREQ(I,1)) ,0.125*FREQ(I,4); !角度[度]
NEXT I
PLOT LINES
! FOR I=1 TO 57 STEP 1 !位相角度[度]
! SET COLOR 3 !3は緑色
! PLOT LINES:LOG10(FREQ(I,1)) ,0.25*FREQ(I,5); !角度[度]
! NEXT I
! PLOT LINES
FOR f=1 TO 6 !y軸が直線目盛り
SET COLOR 4
PLOT TEXT ,AT 5.1,-10*(f-1)-2: mid$(" 0 -80 -160-240-320-400 ",4*(f-1)+1,4)
NEXT f
PRINT
NEXT K ! ここで,利得 Kを変化させる。
十進BASICは,
LET N=1000
DIM A(N)
のような拡張構文を許容するため,配列要素の実領域をヒープ上に確保します。
DIM B(1000)
のようにFull BASIC規格の範囲で宣言された配列はスタックメモリ上に確保できますが,
内部構造の複雑さを避けるためにどちらの形式の配列も配列要素はヒープ上に置いています。
REM 十進BASIC添付"\BASICw32\SAMPLE\INTERPRE.bas"に加筆
REM 行番号のない行が加筆部分。行番号は削除可。
1000 REM Full BASICのモジュールの使い方を示すサンプル
1010 REM
1020 REM 数値式の評価を行う
1030 REM 組込み関数は,SIN,COS,TAN, LOG, EXP, SQR, INT,ABSとPIのみ
1040 REM 大文字と小文字の区別はしない
1050 REM 数値式の文法はほぼFull BASICに準ずるが,関数名に続く括弧は空白を入れずに書く。
1060 REM 数値は,数字で始まり,コンマを1個以下含む数字の列としてのみ書ける。
1070 REM 零除算エラーなどは考慮していない。
1080 DECLARE EXTERNAL FUNCTION interpreter.expression ! 数値式を評価する関数
1090 DECLARE EXTERNAL STRING interpreter.s$ ! 入力行
1100 DECLARE EXTERNAL NUMERIC interpreter.i ! 入力行の文字位置
1110 DECLARE EXTERNAL SUB interpreter.skip ! 空白文字を読み飛ばす副プログラム
DECLARE EXTERNAL FUNCTION interpreter.str_expression$ !文字列式を評価する関数
DECLARE EXTERNAL NUMERIC interpreter.vc,interpreter.sc !変数の個数(vc=数値,sc=文字列)
DECLARE EXTERNAL SUB interpreter.error !エラーメッセージ
1120 LINE INPUT s$
1130 ! LET s$=UCASE$(s$) !文字列の小文字保持のため無効にした
DO
LET vc,sc=0
1140 LET i=1
1150 CALL skip
IF s$(i:i)="$" THEN
LET i=i+1
CALL skip
IF s$(i:i)="=" THEN
LET i=i+1
CALL skip
PRINT str_expression$ ! 文字列式評価
ELSE
CALL error("$=")
END IF
ELSE
1160 PRINT expression ! 数値式評価
END IF
1170 IF i<>LEN(s$)+1 THEN PRINT "Syntax error" ! 比較式をi<LEN(s$)から変更
LOOP UNTIL vc+sc=0 OR i<>LEN(s$)+1 ! 中止は[中止]ボタンで
1180 END
1190 !
1200 MODULE interpreter
! MODULE OPTION ARITHMETIC NATIVE ! DECIMAL_HIGH,COMPLEX,RATIONAL 数値オプション
1210 PUBLIC STRING s$
1220 PUBLIC NUMERIC i
1230 PUBLIC FUNCTION expression
1240 PUBLIC SUB skip
1250 SHARE FUNCTION term,factor,primary,numeric
PUBLIC FUNCTION str_expression$
PUBLIC NUMERIC vc,sc
PUBLIC SUB error
SHARE FUNCTION check,argument,rounding,position,bitval,v_chr,variable
SHARE FUNCTION str_primary$,str_constant$,str_naming$,sub_string$,str_input$,bitstr$
SHARE NUMERIC vari_val(20),inputv ! 20=変数の個数
SHARE STRING sn$,vari_name$(20),string$(20),str_name$(20)
SHARE FUNCTION F1,F2,F3,FS$ !!! ユーザー定義関数
! MODULE OPTION ANGLE DEGREES ! 角の大きさの単位
! MODULE OPTION CHARACTER BYTE ! 文字列処理の単位
LET inputv=0
1260 !
EXTERNAL FUNCTION F1(a) !!! ユーザー定義関数
let F1=a
END FUNCTION
EXTERNAL FUNCTION F2(a,b) !!! ユーザー定義関数
let F2=a+b
END FUNCTION
EXTERNAL FUNCTION F3(a,b,c) !!! ユーザー定義関数
let F3=a+b+c
END FUNCTION
EXTERNAL FUNCTION FS$(a$,b,c) !!! ユーザー定義関数
let FS$=a$&str$(b)&str$(c)
END FUNCTION
!
1270 EXTERNAL SUB skip
1280 DO WHILE s$(i:i)=" "
1290 LET i=i+1
1300 LOOP
1310 END SUB
1320 !
1330 EXTERNAL FUNCTION expression
1340 DECLARE NUMERIC n
1350 DECLARE STRING op$
1360 SELECT CASE s$(i:i)
1370 CASE "-"
1380 LET i=i+1
1390 CALL skip
1400 LET n=-term
1410 CASE "+"
1420 LET i=i+1
1430 CALL skip
1440 LET n=term
1450 CASE ELSE
1460 LET n=term
1470 END SELECT
1480 DO WHILE s$(i:i)="+" OR s$(i:i)="-"
1490 LET op$=s$(i:i)
1500 LET i=i+1
1510 CALL skip
1520 IF op$="+" THEN LET n=n+term ELSE LET n=n-term
1530 LOOP
1540 LET expression =n
1550 CALL skip
1560 END FUNCTION
1570 !
1580 EXTERNAL FUNCTION term
1590 DECLARE NUMERIC n
1600 DECLARE STRING op$
1610 LET n=factor
1620 DO WHILE s$(i:i)="*" OR s$(i:i)="/"
1630 LET op$=s$(i:i)
1640 LET i=i+1
1650 CALL skip
1660 IF op$="*" THEN LET n=n*factor ELSE LET n=n/factor
1670 LOOP
1680 LET term=n
1690 END FUNCTION
1700 !
1710 EXTERNAL FUNCTION factor
1720 DECLARE NUMERIC n
1730 LET n=primary
1740 DO WHILE s$(i:i)="^"
1750 LET i=i+1
1760 CALL skip
1770 LET n=n^primary
1780 LOOP
1790 LET factor=n
1800 END FUNCTION
1810 !
1820 EXTERNAL FUNCTION primary
1830 IF s$(i:i)>="0" AND s$(i:i)<="9" THEN
1840 LET primary=numeric
ELSEIF s$(i:i)="." THEN
LET primary=numeric
1850 ELSEIF UCASE$(s$(i:i+1))="PI" AND check(s$(i+2:i+2))=1 THEN ! 関数check加筆
1860 LET i=i+2
1870 CALL skip
1880 LET primary=PI ! 有理数モード注意
ELSEIF UCASE$(s$(i:i+2))="RND" AND check(s$(i+3:i+3))=1 THEN
LET i=i+3
CALL skip
LET primary=RND ! 変数入力がある数値式では都度更新
ELSEIF UCASE$(s$(i:i+3))="TIME" AND check(s$(i+4:i+4))=1 THEN
LET i=i+4
CALL skip
LET primary=TIME ! 変数入力がある数値式では都度更新
ELSEIF UCASE$(s$(i:i+3))="DATE" AND check(s$(i+4:i+4))=1 THEN
LET i=i+4
CALL skip
LET primary=DATE ! 変数入力がある数値式では都度更新
!ELSEIF UCASE$(s$(i:i+5))="MAXNUM" AND check(s$(i+6:i+6))=1 THEN
! LET i=i+6
! CALL skip
! LET primary=MAXNUM ! 有理数モード不可
1890 ELSE
1900 IF s$(i:i)="(" THEN
1910 LET i=i+1
1920 CALL skip
1930 LET primary=expression
ELSEIF UCASE$(s$(i:i+2))="F1(" THEN !!! ユーザー定義関数
LET i=i+3
CALL skip
LET Primary=F1(expression)
ELSEIF UCASE$(s$(i:i+2))="F2(" THEN !!! ユーザー定義関数
LET i=i+3
CALL skip
LET primary=F2(expression,argument)
ELSEIF UCASE$(s$(i:i+2))="F3(" THEN !!! ユーザー定義関数
LET i=i+3
CALL skip
LET primary=F3(expression,argument,argument)
1940 ELSEIF UCASE$(s$(i:i+3))="SIN(" THEN ! 超越関数
1950 LET i=i+4
1960 CALL skip
1970 LET Primary=SIN(expression)
1980 ELSEIF UCASE$(s$(i:i+3))="COS(" THEN ! 超越関数
1990 LET i=i+4
2000 CALL skip
2010 LET Primary=COS(expression)
2020 ELSEIF UCASE$(s$(i:i+3))="TAN(" THEN ! 超越関数
2030 LET i=i+4
2040 CALL skip
2050 LET Primary=TAN(expression)
2060 ELSEIF UCASE$(s$(i:i+3))="LOG(" THEN ! 超越関数
2070 LET i=i+4
2080 CALL skip
2090 LET Primary=LOG(expression)
2100 ELSEIF UCASE$(s$(i:i+3))="EXP(" THEN ! 超越関数
2110 LET i=i+4
2120 CALL skip
2130 LET Primary=EXP(expression)
2140 ELSEIF UCASE$(s$(i:i+3))="SQR(" THEN ! 有理数モード注意
2150 LET i=i+4
2160 CALL skip
2170 LET Primary=SQR(expression)
2180 ELSEIF UCASE$(s$(i:i+3))="INT(" THEN
2190 LET i=i+4
2200 CALL skip
2210 LET Primary=INT(expression)
2220 ELSEIF UCASE$(s$(i:i+3))="ABS(" THEN
2230 LET i=i+4
2240 CALL skip
2250 LET Primary=ABS(expression)
ELSEIF UCASE$(s$(i:i+3))="MOD(" THEN
LET i=i+4
CALL skip
LET primary=MOD(expression,argument)
ELSEIF UCASE$(s$(i:i+5))="ROUND(" THEN
LET i=i+6
CALL skip
LET primary=rounding
ELSEIF UCASE$(s$(i:i+4))="CEIL(" THEN
LET i=i+5
CALL skip
LET Primary=CEIL(expression)
ELSEIF UCASE$(s$(i:i+3))="SGN(" THEN
LET i=i+4
CALL skip
LET Primary=SGN(expression)
ELSEIF UCASE$(s$(i:i+2))="IP(" THEN
LET i=i+3
CALL skip
LET Primary=IP(expression)
ELSEIF UCASE$(s$(i:i+2))="FP(" THEN
LET i=i+3
CALL skip
LET Primary=FP(expression)
ELSEIF UCASE$(s$(i:i+9))="REMAINDER(" THEN
LET i=i+10
CALL skip
LET primary=REMAINDER(expression,argument)
ELSEIF UCASE$(s$(i:i+8))="TRUNCATE(" THEN
LET i=i+9
CALL skip
LET primary=TRUNCATE(expression,argument)
ELSEIF UCASE$(s$(i:i+4))="LOG2(" THEN ! 超越関数
LET i=i+5
CALL skip
LET Primary=LOG2(expression)
ELSEIF UCASE$(s$(i:i+5))="LOG10(" THEN ! 超越関数
LET i=i+6
CALL skip
LET Primary=LOG10(expression)
ELSEIF UCASE$(s$(i:i+3))="CSC(" THEN ! 超越関数
LET i=i+4
CALL skip
LET Primary=CSC(expression)
ELSEIF UCASE$(s$(i:i+3))="SEC(" THEN ! 超越関数
LET i=i+4
CALL skip
LET Primary=SEC(expression)
ELSEIF UCASE$(s$(i:i+3))="COT(" THEN ! 超越関数
LET i=i+4
CALL skip
LET Primary=COT(expression)
ELSEIF UCASE$(s$(i:i+4))="ASIN(" THEN ! 超越関数
LET i=i+5
CALL skip
LET Primary=ASIN(expression)
ELSEIF UCASE$(s$(i:i+4))="ACOS(" THEN ! 超越関数
LET i=i+5
CALL skip
LET Primary=ACOS(expression)
ELSEIF UCASE$(s$(i:i+3))="ATN(" THEN ! 超越関数
LET i=i+4
CALL skip
LET Primary=ATN(expression)
ELSEIF UCASE$(s$(i:i+5))="ANGLE(" THEN ! 超越関数
LET i=i+6
CALL skip
LET primary=ANGLE(expression,argument)
ELSEIF UCASE$(s$(i:i+4))="SINH(" THEN ! 超越関数
LET i=i+5
CALL skip
LET Primary=SINH(expression)
ELSEIF UCASE$(s$(i:i+4))="COSH(" THEN ! 超越関数
LET i=i+5
CALL skip
LET Primary=COSH(expression)
ELSEIF UCASE$(s$(i:i+4))="TANH(" THEN ! 超越関数
LET i=i+5
CALL skip
LET Primary=TANH(expression)
!ELSEIF UCASE$(s$(i:i+3))="EPS(" THEN ! 有理数モード不可
! LET i=i+4
! CALL skip
! LET Primary=EPS(expression)
ELSEIF UCASE$(s$(i:i+3))="DEG(" THEN
LET i=i+4
CALL skip
LET Primary=DEG(expression)
ELSEIF UCASE$(s$(i:i+3))="RAD(" THEN
LET i=i+4
CALL skip
LET Primary=RAD(expression)
ELSEIF UCASE$(s$(i:i+3))="MAX(" THEN
LET i=i+4
CALL skip
LET primary=MAX(expression,argument)
ELSEIF UCASE$(s$(i:i+3))="MIN(" THEN
LET i=i+4
CALL skip
LET primary=MIN(expression,argument)
ELSEIF UCASE$(s$(i:i+4))="FACT(" THEN !十進BASIC独自拡張
LET i=i+5
CALL skip
LET Primary=FACT(expression)
ELSEIF UCASE$(s$(i:i+4))="PERM(" THEN !十進BASIC独自拡張
LET i=i+5
CALL skip
LET primary=PERM(expression,argument)
ELSEIF UCASE$(s$(i:i+4))="COMB(" THEN !十進BASIC独自拡張
LET i=i+5
CALL skip
LET primary=COMB(expression,argument)
ELSEIF UCASE$(s$(i:i+10))="COLORINDEX(" THEN !十進BASIC独自拡張
LET i=i+11
CALL skip
LET primary=COLORINDEX(expression,argument,argument)
!ELSEIF UCASE$(s$(i:i+7))="COMPLEX(" THEN !複素関数
! LET i=i+8
! CALL skip
! LET primary=COMPLEX(expression,argument)
!ELSEIF UCASE$(s$(i:i+2))="RE(" THEN !複素関数
! LET i=i+3
! CALL skip
! LET Primary=RE(expression)
!ELSEIF UCASE$(s$(i:i+2))="IM(" THEN !複素関数
! LET i=i+3
! CALL skip
! LET Primary=IM(expression)
!ELSEIF UCASE$(s$(i:i+4))="CONJ(" THEN !複素関数
! LET i=i+5
! CALL skip
! LET Primary=CONJ(expression)
!ELSEIF UCASE$(s$(i:i+3))="ARG(" THEN !複素関数
! LET i=i+4
! CALL skip
! LET Primary=ARG(expression)
!ELSEIF UCASE$(s$(i:i+5))="NUMER(" THEN !有理数モード専用
! LET i=i+6
! CALL skip
! LET Primary=NUMER(expression)
!ELSEIF UCASE$(s$(i:i+5))="DENOM(" THEN !有理数モード専用
! LET i=i+6
! CALL skip
! LET Primary=DENOM(expression)
!ELSEIF UCASE$(s$(i:i+3))="GCD(" THEN !有理数モード専用
! LET i=i+4
! CALL skip
! LET primary=GCD(expression,argument)
!ELSEIF UCASE$(s$(i:i+6))="INTSQR(" THEN !有理数モード専用
! LET i=i+7
! CALL skip
! LET Primary=INTSQR(expression)
!ELSEIF UCASE$(s$(i:i+7))="INTLOG2(" THEN !有理数モード専用
! LET i=i+8
! CALL skip
! LET Primary=INTLOG2(expression)
ELSEIF UCASE$(s$(i:i+3))="LEN(" THEN
LET i=i+4
CALL skip
LET primary=LEN(str_expression$)
ELSEIF UCASE$(s$(i:i+3))="POS(" THEN
LET i=i+4
CALL skip
LET primary=position
ELSEIF UCASE$(s$(i:i+3))="VAL(" THEN
LET i=i+4
CALL skip
LET primary=VAL(str_expression$)
ELSEIF UCASE$(s$(i:i+3))="ORD(" THEN
LET i=i+4
CALL skip
LET primary=ORD(str_expression$)
ELSEIF UCASE$(s$(i:i+4))="BVAL(" THEN
LET i=i+5
CALL skip
LET primary=bitval
ELSEIF UCASE$(s$(i:i+4))="BLEN(" THEN !十進BASIC独自拡張
LET i=i+5
CALL skip
LET primary=BLEN(str_expression$)
ELSEIF v_chr(s$(i:i))=1 THEN
LET primary=variable ! 変数
CALL skip
EXIT FUNCTION
2260 ELSE
CALL error("FUNCTION primary")
2270 PRINT "Syntax error"
2280 STOP
2290 END IF
2300 IF s$(i:i)=")" THEN
2310 LET i=i+1
2320 CALL skip
2330 ELSE
CALL error("FUNCTION primary")
2340 PRINT "Syntax error"
2350 STOP
2360 END IF
2370 END IF
2380 END FUNCTION
2390 !
2400 EXTERNAL FUNCTION numeric
2410 DECLARE NUMERIC i0
2420 CALL skip
2430 LET i0=i
IF s$(i:i)="." THEN ! 小数点で始まる
LET i=i+1
ELSE
2440 DO WHILE s$(i:i)>="0" AND s$(i:i)<="9"
2450 LET i=i+1
2460 LOOP
2470 IF s$(i:i)="." THEN LET i=i+1
END IF
2480 DO WHILE s$(i:i)>="0" AND s$(i:i)<="9"
2490 LET i=i+1
2500 LOOP
IF LEN(s$)>=i AND UCASE$(s$(i:i))="E" THEN ! 指数部
LET i=i+1
IF s$(i:i)="+" OR s$(i:i)="-" THEN LET i=i+1
DO WHILE s$(i:i)>="0" AND s$(i:i)<="9"
LET i=i+1
LOOP
END IF
2510 LET numeric=VAL(s$(i0:i-1))
2520 CALL skip
2530 END FUNCTION
2540 !
![その2]へ続く
! [その2]
! *以下すべて加筆部分*
EXTERNAL FUNCTION check(c$) !! 予約語の後続字
DECLARE STRING p$
LET check=-1
DO
READ IF MISSING THEN EXIT DO : p$
IF c$=p$ THEN LET check=1
LOOP
DATA " " , "+" , "-" , "*" , "/" , "^" , "," , ")" , ""
END FUNCTION
!
EXTERNAL FUNCTION argument !! 引数
CALL skip
IF s$(i:i)="," THEN
LET i=i+1
CALL skip
ELSE
CALL error("FUNCTION argument,引数")
END IF
LET argument=expression
END FUNCTION
!
EXTERNAL FUNCTION rounding !! 関数ROUNDの識別
DECLARE NUMERIC a
LET a=expression
IF s$(i:i)="," THEN
LET i=i+1
CALL skip
LET rounding=ROUND(a,expression)
ELSEIF s$(i:i)=")" THEN
LET rounding=ROUND(a) ! 十進BASIC独自拡張
ELSE
CALL error("FUNCTION rounding,関数ROUND")
END IF
END FUNCTION
!
EXTERNAL FUNCTION position !! 関数POSの識別
DECLARE STRING aa$,bb$
LET aa$=str_expression$
IF s$(i:i)="," THEN
LET i=i+1
CALL skip
LET bb$=str_expression$
IF s$(i:i)=")" THEN
LET position=POS(aa$,bb$)
ELSEIF s$(i:i)="," THEN
LET i=i+1
CALL skip
LET position=POS(aa$,bb$,expression)
ELSE
CALL error("FUNCTION position,関数POS")
END IF
ELSE
CALL error("FUNCTION position,関数POS")
END IF
END FUNCTION
!
EXTERNAL FUNCTION bitval !! 関数BVALの識別
DECLARE STRING aa$
LET aa$=str_primary$
IF s$(i:i)="," THEN
LET i=i+1
CALL skip
IF s$(i:i)="2" THEN
LET i=i+1
CALL skip
LET bitval=BVAL(aa$,2)
ELSEIF s$(i:i+1)="16" THEN
LET i=i+2
CALL skip
LET bitval=BVAL(aa$,16)
ELSE
CALL error("FUNCTION bitval,関数BVAL")
END IF
ELSE
CALL error("FUNCTION bitval,関数BVAL")
END IF
END FUNCTION
!
EXTERNAL FUNCTION v_chr(c$) !! 変数名文字
IF c$>="A" AND c$<="Z" OR c$>="a" AND c$<="z" OR c$>="ぁ" THEN !先頭文字及びそれ以降
LET v_chr=1
ELSEIF c$>="0" AND c$<="9" OR c$="_" OR c$>="0" THEN ! 2文字目以降
LET v_chr=2
ELSE
LET v_chr=-1
END IF
END FUNCTION
!
EXTERNAL FUNCTION variable !! 変数
DECLARE NUMERIC j,vi
DECLARE STRING vn$,aa$,vs$
LET vn$=""
DO WHILE v_chr(s$(i:i))>=1
LET vn$=vn$&s$(i:i)
LET i=i+1
LOOP
FOR j=1 TO vc
IF UCASE$(vn$)=UCASE$(vari_name$(j)) THEN
LET variable=vari_val(j) ! 既出の変数
EXIT FUNCTION
END IF
NEXT j
LET vc=vc+1
LET vari_name$(vc)=vn$
IF inputv=0 THEN
DO
LINE INPUT PROMPT vn$&"=" : aa$ ! 変数への入力
LOOP UNTIL aa$<>""
ELSE
CALL error("FUNCTION variable,変数入力")
END IF
LET vs$=s$
LET vi=i
LET s$=LTRIM$(aa$)
LET i=1
LET inputv=1
LET vari_val(vc)=expression ! 変数に入力した数値式の処理
LET inputv=0
LET s$=vs$
LET i=vi
LET variable=vari_val(vc)
END FUNCTION
!
!
EXTERNAL FUNCTION str_expression$ !! 文字列式
DECLARE STRING str_n$
LET str_n$=str_primary$
DO WHILE s$(i:i)="&"
LET i=i+1
CALL skip
LET str_n$=str_n$&str_primary$
LOOP
LET str_expression$ =str_n$
CALL skip
END FUNCTION
!
EXTERNAL FUNCTION str_primary$ !! 文字列一次子
DECLARE NUMERIC j
IF s$(i:i)="""" THEN
LET i=i+1
LET str_primary$=str_constant$
ELSEIF UCASE$(s$(i:i+4))="DATE$" THEN
LET i=i+5
CALL skip
LET str_primary$=DATE$ !変数入力がある数値式では都度更新
ELSEIF UCASE$(s$(i:i+4))="TIME$" THEN
LET i=i+5
CALL skip
LET str_primary$=TIME$ !変数入力がある数値式では都度更新
ELSE
IF v_chr(s$(i:i))=1 THEN
LET sn$=str_naming$ ! 文字列関数/変数名
FOR j=1 TO sc
IF UCASE$(sn$)=UCASE$(str_name$(j)) THEN
CALL skip
IF s$(i:i)="(" THEN
LET i=i+1
CALL skip
LET str_primary$=sub_string$(string$(j)) !部分文字列
ELSE
LET str_primary$=string$(j) ! 既出の文字列変数
END IF
EXIT FUNCTION
END IF
NEXT j
ELSE
CALL error("FUNCTION str_primary$,文字列一次子")
END IF
SELECT CASE UCASE$(sn$)&s$(i:i)
CASE "FS$(" !!! ユーザー定義関数
LET i=i+1
CALL skip
LET str_primary$=FS$(str_expression$,argument,argument)
CASE "REPEAT$("
LET i=i+1
CALL skip
LET str_primary$=REPEAT$(str_expression$,argument)
CASE "STR$("
LET i=i+1
CALL skip
LET str_primary$=STR$(expression)
CASE "USING$("
LET i=i+1
CALL skip
LET str_primary$=USING$(str_expression$,argument)
CASE "CHR$("
LET i=i+1
CALL skip
LET str_primary$=CHR$(expression)
CASE "LCASE$("
LET i=i+1
CALL skip
LET str_primary$=LCASE$(str_expression$)
CASE "UCASE$("
LET i=i+1
CALL skip
LET str_primary$=UCASE$(str_expression$)
CASE "LTRIM$("
LET i=i+1
CALL skip
LET str_primary$=LTRIM$(str_expression$)
CASE "RTRIM$("
LET i=i+1
CALL skip
LET str_primary$=RTRIM$(str_expression$)
CASE "BSTR$("
LET i=i+1
CALL skip
LET str_primary$=bitstr$
CASE "SUBSTR$(" ! 十進BASIC独自拡張
LET i=i+1
CALL skip
LET str_primary$=SUBSTR$(str_expression$,argument,argument)
CASE "MID$(" ! 十進BASIC独自拡張
LET i=i+1
CALL skip
LET str_primary$=MID$(str_expression$,argument,argument)
CASE "LEFT$(" ! 十進BASIC独自拡張
LET i=i+1
CALL skip
LET str_primary$=LEFT$(str_expression$,argument)
CASE "RIGHT$(" ! 十進BASIC独自拡張
LET i=i+1
CALL skip
LET str_primary$=RIGHT$(str_expression$,argument)
CASE ELSE
LET str_primary$=str_input$ ! 文字列入力
CALL skip
EXIT FUNCTION
END SELECT
IF s$(i:i)=")" THEN
LET i=i+1
CALL skip
ELSE
CALL error("FUNCTION str_primary$")
END IF
END IF
END FUNCTION
!
EXTERNAL FUNCTION str_constant$ !! 文字列定数
DECLARE STRING cc$
LET cc$=""
DO
IF s$(i:i)="""" THEN
IF s$(i+1:i+1)="""" THEN ! [""]の識別
LET cc$=cc$&s$(i:i)
LET i=i+2
ELSE
LET i=i+1
EXIT DO
END IF
ELSE
LET cc$=cc$&s$(i:i)
LET i=i+1
IF i>LEN(s$)+1 THEN
CALL error("FUNCTION str_constant$,文字列定数")
EXIT DO
END IF
END IF
LOOP
CALL skip
LET str_constant$=cc$
END FUNCTION
!
EXTERNAL FUNCTION str_naming$ !! 文字列関数/変数名
LET sn$=""
DO WHILE v_chr(s$(i:i))>=1
LET sn$=sn$&s$(i:i)
LET i=i+1
LOOP
IF s$(i:i)="$" THEN
LET str_naming$=sn$&s$(i:i)
LET i=i+1
ELSE
CALL error("FUNCTION str_naming$,文字列関数/変数名")
END IF
END FUNCTION
!
EXTERNAL FUNCTION sub_string$(ss$) !! 部分文字列
DECLARE NUMERIC a
LET a=expression
IF s$(i:i)=":" THEN
LET i=i+1
CALL skip
LET sub_string$=ss$(a:expression)
IF s$(i:i)=")" THEN
LET i=i+1
CALL skip
ELSE
CALL error("FUNCTION sub_string$,部分文字列")
END IF
ELSE
CALL error("FUNCTION sub_string$,部分文字列")
END IF
END FUNCTION
!
EXTERNAL FUNCTION str_input$ !! 文字列入力
DECLARE NUMERIC j,vi
DECLARE STRING vs$
LET sc=sc+1
LET str_name$(sc)=sn$
IF inputv=0 THEN
LINE INPUT PROMPT sn$&"=" : string$(sc)
ELSE
CALL error("FUNCTION str_input$,文字列入力")
END IF
LET j=1
DO WHILE string$(sc)(j:j)=" "
LET j=j+1
LOOP
IF string$(sc)(j:j)="$" THEN
LET j=j+1
DO WHILE string$(sc)(j:j)=" "
LET j=j+1
LOOP
IF string$(sc)(j:j)="=" THEN
LET vs$=s$
LET vi=i
LET s$=string$(sc)(j+1:LEN(string$(sc)))
LET s$=LTRIM$(s$)
LET i=1
LET inputv=1
LET string$(sc)=str_expression$ ! 文字列変数に入力した文字列式の処理
LET inputv=0
LET s$=vs$
LET i=vi
END IF
END IF
LET str_input$=string$(sc)
END FUNCTION
!
EXTERNAL FUNCTION bitstr$ !! 関数BSTR$の識別
DECLARE NUMERIC a
LET a=expression
IF s$(i:i)="," THEN
LET i=i+1
CALL skip
IF s$(i:i)="2" THEN
LET i=i+1
CALL skip
LET bitstr$=BSTR$(a,2)
ELSEIF s$(i:i+1)="16" THEN
LET i=i+2
CALL skip
LET bitstr$=BSTR$(a,16)
ELSE
CALL error("FUNCTION bitstr$,関数BSTR$")
END IF
ELSE
CALL error("FUNCTION bitstr$,関数BSTR$")
END IF
END FUNCTION
!
EXTERNAL SUB error(e$) !! エラー表示
PRINT "Error (";e$;")"
!STOP
END SUB
!
2550 END MODULE
OPTION ARITHMETIC COMPLEX
LET j=SQR(-1) !虚数単位
LET f=60 !周波数[Hz]
DEF w=2*PI*f !角周波数ω
SUB DispS(z) !複素数をS表示する ※スタインメッツ(Steinmetz)
PRINT ABS(z);
IF ABS(z)<>0 THEN
IF arg(z)<>0 THEN PRINT "∠";DEG(arg(z));"°";
END IF
PRINT
END SUB
!-------------------- ここまでがサブルーチン
!---------- ↓↓↓↓↓ ----------
LET xmax=6 !<----- ※要調整
LET ymin=-50
LET ymax=5
!●回路図 CRローパス・フィルタ
!vi・─R1┬─・vo
! C1
! │
! ≡
! 参考サイト http://sim.okawa-denshi.jp/CRlowkeisan.htm
LET R1=1.6e3 !1.6k[Ω]
LET C1=0.1e-6 !0.1μ[F]
DEF G(s)=1/(s*C1*R1+1) !入出力システムの伝達関数 G(s)=Vo/Vi=(1/(C1*R1))/(s+1/(C1*R1))
!---------- ↑↑↑↑↑ ----------
!!!SET bitmap SIZE 600,600 !画面を大きくする
SET WINDOW -0.5,xmax+0.5, ymin,ymax !表示領域
DRAW grid(1,5) !左端の目盛り
FOR f=1 TO xmax !x軸が対数
PLOT TEXT ,AT f-0.3,-0.15: mid$("10 100 1k 10k 100k1M 10M 100M",4*(f-1)+1,4)
NEXT f
FOR xx=0 TO xmax STEP 0.025 !周波数[Hz]
LET f=10^xx !xx=LOG10(f)
LET t=ABS(G(j*w))
PLOT LINES: xx,20*LOG10(t); !利得[dB]
NEXT xx
PLOT LINES
SET TEXT COLOR 2
FOR k=ymax TO ymin STEP -5 !右端の縦軸目盛り
PLOT TEXT ,AT xmax,k: STR$(k*2)&"°" !※利得のグラフに合わせるために2倍する
NEXT k
SET LINE COLOR 2
FOR xx=0 TO xmax STEP 0.05 !周波数[Hz]
LET f=10^xx
LET th=arg(G(j*w))
IF th>0 THEN LET th=th-2*PI !0〜-2πへ補正する <----- ※要調整
PLOT LINES: xx,DEG(th)/2; !位相θ[deg] ※利得のグラフに合わせるために1/2倍する
NEXT xx
PLOT LINES
END
●伝達関数による過渡解析
OPTION ARITHMETIC COMPLEX
DECLARE EXTERNAL SUB IFFT !逆フーリエ変換
DEF C(s)=G(s)*R(s) !応答関数
DEF R(s)=1/s !指令関数 ※ステップ関数
LET Vi=1 !1∠0°[V] ※仮の電圧源
!----- ↓↓↓↓↓ -----
LET T=2e-3 !時間区間 [0,T]
!●回路図 CRローパス・フィルタ
!vi・─R1┬─・vo
! C1
! │
! ≡
! 参考サイト http://sim.okawa-denshi.jp/CRlowkeisan.htm
LET R1=1.6e3 !1.6k[Ω]
LET C1=0.1e-6 !0.1μ[F]
DEF G(s)=1/(s*C1*R1+1) !入出力システムの伝達関数 G(s)=Vo/Vi=(1/(C1*R1))/(s+1/(C1*R1))
!----- ↑↑↑↑↑ -----
!逆ラプラス変換
! f(t)=lim [ω→∞] { 1/(2π*j)∫F(s)*Exp(s*t)ds [γ-j*ω,γ+j*ω] }、jは虚数単位、γ>0とωは実数。
!s=γ+j*2πωとすると、ds=j*2πdω。
!これを上式に代入して、変形すると、
! f(t)=Exp(γt)∫F(γ,ω)*Exp(j*2πω)dω [-∞,∞]
!右辺の積分部分は逆フーリエ変換。
LET N=1024*8 !データ総数 ※2のべき乗、大きいほど精度がよい
DIM d(0 TO N-1) !入出力用配列
LET Gamma=5 !※3〜7
!γを大きくすれば精度は上がりそうだが、
!あとでExp(γt)をかけるので、tが大きいところで発散する。
LET rr=Gamma/T !γを決める
FOR k=0 TO N/2 !変換データの作成
LET Cs=C( COMPLEX(rr, 2*PI*k/T) ) !sk=γ+j*2π*k/T、k=0〜n-1
LET Hw=(COS(2*PI*k/N)+1)/2 !データは離散なため、ハニング関数をかけて平滑化する ※精度の向上
LET d(k)=N/T*Cs*Hw !n/T*Y(k) * Hw 0〜N/2
IF NOT(k=0 OR k=N/2) THEN LET d(N-k)=COMPLEX(Re(d(k)),-Im(d(k))) !N-1〜N/2+1は、共役複素数
NEXT k
CALL IFFT(d) !高速逆フーリエ変換
SET WINDOW -T/8,T,-Vi*1.2,Vi*1.2 !表示領域
DRAW grid(T/4,Vi/5)
PLOT TEXT ,AT T*7/8,0: "[秒]"
LET dt=T/N !時間刻み幅 ��t
FOR k=0 TO N-1 STEP 8 !結果の表示 [0,T]
LET tt=k*dt !経過時間
PLOT LINES: tt, Re(d(k))*EXP(rr*tt); !Exp(γt)をかける ※Exp(γ*k*T/n)、k=0〜n-1
PRINT Re(d(k))*EXP(rr*tt) !debug
NEXT k
END
EXTERNAL SUB IFFT(x()) !高速逆フーリエ変換 x() : 入力/出力データ
OPTION ARITHMETIC COMPLEX
DECLARE EXTERNAL SUB FFTMAIN
LET nx=SIZE(x)
LET theta=2*PI/nx ! W = Exp(-j * 2π/N * -1) = Exp(j * theta)とする
CALL FFTMAIN(x, theta)
MAT x=(1/nx)*x
END SUB
EXTERNAL SUB FFTMAIN(x(), theta)
OPTION ARITHMETIC COMPLEX
LET nx=SIZE(x)
IF MOD(nx, 2)<>0 THEN !DFTの計算
DIM w(0 TO nx-1), xtmp(0 TO nx-1)
MAT xtmp=x
FOR k=0 TO nx-1
LET tmp=theta*k
FOR n=0 TO nx-1
LET w(n)=EXP( COMPLEX(0, tmp*n) )
NEXT n
LET x(k)=DOT(w, xtmp)
NEXT k
ELSE !2分して再帰呼出し
LET hnx=nx/2
DIM x0(0 TO hnx-1), x1(0 TO hnx-1)
FOR k=0 TO hnx-1
LET x0(k)=x(k)+x(k+hnx)
LET wk=EXP( COMPLEX(0, theta*k) )
LET x1(k)=wk*(x(k)-x(k+hnx))
NEXT k
CALL FFTMAIN(x0, 2*theta)
CALL FFTMAIN(x1, 2*theta)
FOR k=0 TO hnx-1
LET x(2*k)=x0(k)
LET x(2*k+1)=x1(k)
NEXT k
END IF
END SUB
LET Vi=1 !1∠0°[V] ※仮の電圧源
FUNCTION Laplace(e$,Z,s) !ラプラス変換
SELECT CASE UCASE$(e$)
CASE "R"
LET Laplace=Z !R*i(t)
CASE "L"
LET Laplace=s*Z !L*d{i(t)}/dt
CASE "C"
LET Laplace=1/(s*Z) !1/C*∫{i(t)}dt
CASE ELSE
PRINT "未サポートの素子です。"
STOP
END SELECT
END FUNCTION
!●回路図 CRローパス・フィルタ
! a
!vi・─R1┬─・vo
! C2
! │
! ≡
! 参考サイト http://sim.okawa-denshi.jp/CRlowkeisan.htm
!----- ↓↓↓↓↓ -----
LET M=2 !素子の数
!----- ↑↑↑↑↑ -----
DIM A(M,M),x(M),b(M) !A*x=b ※Z(s)*I(s)=E(s)
DIM iA(M,M)
FUNCTION G(s) !伝達関数
MAT A=ZER !A(式の番号,素子の番号) ※下記の設定で0は省略するため、あらかじめ0を入れておく
MAT b=ZER !b(式の番号) ※電流または電圧の和
!---------- ↓↓↓↓↓ ----------
LET R1=Laplace("R",1.6e3,s) !1.6k[Ω]
LET C2=Laplace("C",0.1e-6,s) !0.1μ[F]
!キルヒホッフの電流則
LET A(1,1)=1 !節点a i1(t)-i2(t)=0 ⇒ I1(s)-I2(s)=0
LET A(1,2)=-1
!キルヒホッフの電圧則
LET A(2,1)=R1 !網目 R1*i1(t) +1/C2*∫i2(t)dt =Vi(t) ⇒ R1*I1(s)+1/(s*C2)*I2(s)=Vi(s)
LET A(2,2)=C2
LET b(2)=Vi
!---------- ↑↑↑↑↑ ----------
MAT iA=INV(A)
MAT x=iA*b !各素子の電流I(s)を求める
!!!mat print x
!---------- ↓↓↓↓↓ ----------
LET Vo=C2*x(2) ! Vo(t)=1/C2*∫i2(t)dt ⇒ Vo(s)=1/(s*C2)*I2(s)
!---------- ↑↑↑↑↑ ----------
LET G=Vo/Vi
END FUNCTION
!---------- ↑↑↑↑↑ ----------
OPTION ARITHMETIC COMPLEX
LET j=SQR(-1) !虚数単位
LET f=60 !周波数[Hz]
DEF w=2*PI*f !角周波数ω
SUB DispS(z) !複素数をS表示する ※スタインメッツ(Steinmetz)
PRINT ABS(z);
IF ABS(z)<>0 THEN
IF arg(z)<>0 THEN PRINT "∠";DEG(arg(z));"°";
END IF
PRINT
END SUB
!-------------------- ここまでがサブルーチン
!---------- ↓↓↓↓↓ ----------
LET xmax=6 !<----- ※要調整
LET ymin=-50
LET ymax=5
LET Vi=1 !1∠0°[V] ※仮の電圧源
FUNCTION Laplace(e$,Z,s) !ラプラス変換
SELECT CASE UCASE$(e$)
CASE "R"
LET Laplace=Z !R*i(t)
CASE "L"
LET Laplace=s*Z !L*d{i(t)}/dt
CASE "C"
LET Laplace=1/(s*Z) !1/C*∫{i(t)}dt
CASE ELSE
PRINT "未サポートの素子です。"
STOP
END SELECT
END FUNCTION
!●回路図 CRローパス・フィルタ
! a
!vi・─R1┬─・vo
! C2
! │
! ≡
! 参考サイト http://sim.okawa-denshi.jp/CRlowkeisan.htm
!----- ↓↓↓↓↓ -----
LET M=2 !素子の数
!----- ↑↑↑↑↑ -----
DIM A(M,M),x(M),b(M) !A*x=b ※Z(s)*I(s)=E(s)
DIM iA(M,M)
FUNCTION G(s) !伝達関数
MAT A=ZER !A(式の番号,素子の番号) ※下記の設定で0は省略するため、あらかじめ0を入れておく
MAT b=ZER !b(式の番号) ※電流または電圧の和
!---------- ↓↓↓↓↓ ----------
LET R1=Laplace("R",1.6e3,s) !1.6k[Ω]
LET C2=Laplace("C",0.1e-6,s) !0.1μ[F]
!キルヒホッフの電流則
LET A(1,1)=1 !節点a i1(t)-i2(t)=0 ⇒ I1(s)-I2(s)=0
LET A(1,2)=-1
!キルヒホッフの電圧則
LET A(2,1)=R1 !網目 R1*i1(t) +1/C2*∫i2(t)dt =Vi(t) ⇒ R1*I1(s)+1/(s*C2)*I2(s)=Vi(s)
LET A(2,2)=C2
LET b(2)=Vi
!---------- ↑↑↑↑↑ ----------
MAT iA=INV(A)
MAT x=iA*b !各素子の電流I(s)を求める
!!!mat print x
!---------- ↓↓↓↓↓ ----------
LET Vo=C2*x(2) ! Vo(t)=1/C2*∫i2(t)dt ⇒ Vo(s)=1/(s*C2)*I2(s)
!---------- ↑↑↑↑↑ ----------
LET G=Vo/Vi
END FUNCTION
!---------- ↑↑↑↑↑ ----------
!!!SET bitmap SIZE 600,600 !画面を大きくする
SET WINDOW -0.5,xmax+0.5, ymin,ymax !表示領域
DRAW grid(1,5) !左端の目盛り
FOR f=1 TO xmax !x軸が対数
PLOT TEXT ,AT f-0.3,-0.15: mid$("10 100 1k 10k 100k1M 10M 100M",4*(f-1)+1,4)
NEXT f
FOR xx=0 TO xmax STEP 0.025 !周波数[Hz]
LET f=10^xx !xx=LOG10(f)
LET t=ABS(G(j*w))
PLOT LINES: xx,20*LOG10(t); !利得[dB]
NEXT xx
PLOT LINES
SET TEXT COLOR 2
FOR k=ymax TO ymin STEP -5 !右端の縦軸目盛り
PLOT TEXT ,AT xmax,k: STR$(k*2)&"°" !※利得のグラフに合わせるために2倍する
NEXT k
SET LINE COLOR 2
FOR xx=0 TO xmax STEP 0.05 !周波数[Hz]
LET f=10^xx
LET th=arg(G(j*w))
IF th>0 THEN LET th=th-2*PI !0〜-2πへ補正する <----- ※要調整
PLOT LINES: xx,DEG(th)/2; !位相θ[deg] ※利得のグラフに合わせるために1/2倍する
NEXT xx
PLOT LINES
END
! Rsを付加するのは、良くありません。
! 下の2つの回路は、同じものです。テブナンの定理を。
!
┌─C2─┬──────┐
!
│ │ ┌──┐ │
!
│ └─┤- │ │
!
│ │ ├─�エ�
! ┌─R1─�;�R2─�※�R3─��─┤+ │ ↑ V5
!
↑ ↑V1 ↑V2 ↑V3└──┘ │
!
Vin
C1 C3
K=1 │
!
│ │ │ │
! 0───┴───────┴──────┴─
!
! |(1/R1)+(1/R2)+ω*C1*j
-(1/R2)
0 |
|V1| |Vin/R1|
!
|-(1/R2)
(1/R2)+(1/R3)+ω*C2*j -(1/R3)-K*ω*C2*j| |V2|=| 0 |
!
|0
-(1/R3)
(1/R3)+ω*C3*j | |V3| | 0 |
!
!
┌─C2─┬──────┐
!
│ │ ┌──┐ │
!
│ └─┤- │ │
!
┌─────┐ │ │ ├─�エ�
! │ ┌─R1─�;�R2─�※�R3─��─┤+ │ ↑ V5
!
↑ │
↑V1 ↑V2 ↑V3└──┘ │
! Is=Vin/R1
│ C1 C3
K=1 │
!
↑ │ │ │ │
! ┴─0───┴───────┴──────┴─
!
! K≒1は、ボルテージフォロアとしての利得で、AMP自体の電圧利得は、10E6 程度に極めて大きい。
! 回路上で、K<>1にするには、
! V5〜Amp(-in)間に、減衰器を挿入→ K>1、減衰器出力内部抵抗は、大きくても可。
! V5〜C2 間に、減衰器を挿入→ K<1、減衰器出力内部抵抗は、十分に小さい事。
!
OPTION ANGLE DEGREES
OPTION ARITHMETIC COMPLEX
LET j=COMPLEX(0,1)
LET NP=3
DIM FREQ(57,5), A(NP,NP), T(NP,NP), EOUT(NP,1), B(NP,1)
!----
! 周波数10Hz~100KHz、等比ステップ
FOR i=1 TO 57
LET FREQ(i,1)=10^(1+4*(i-1)/56)
NEXT i
!----
! CR 3段回路
LET R1=51000 !Ω
LET R2=82000 !Ω
LET R3=39000 !Ω
LET C1=0.00685/(10^6) !F
LET C2=0.022/(10^6) !F
LET C3=330/(10^12) !F
!----
SET WINDOW 0.5,5.5, -55,5
DRAW grid(1,5)
FOR K=1-0.0125 TO 1.0125 STEP 0.0125
FOR P=1 TO 57
LET ω=(2*PI*FREQ(P,1))
!
LET A(1,1)=(1/R1)+(1/R2)+j*ω*C1
LET A(1,2)=-(1/R2)
LET A(1,3)=0
!
LET A(2,1)=-(1/R2)
LET A(2,2)=(1/R2)+(1/R3)+j*ω*C2
LET A(2,3)=-(1/R3)-K*j*ω*C2
!
LET A(3,1)=0
LET A(3,2)=-(1/R3)
LET A(3,3)=(1/R3)+j*ω*C3
!
LET Vin=1 !1V
LET B(1,1)=(Vin/R1) !電圧源Vin 直列抵抗R1を、電流源Vin/R1 並列抵抗R1 に変形。
LET B(2,1)=0
LET B(3,1)=0
MAT T=INV(A)
MAT EOUT=T*B
LET EE1=EOUT(1,1)
LET EE2=EOUT(2,1)
LET EE3=EOUT(3,1)
!
LET Gv=K*EOUT(3,1)/Vin
LET FREQ(P,2)=20*LOG10(ABS(Gv))
LET Pv=arg(Gv)
IF Pv>0 THEN LET Pv=Pv-360
LET FREQ(P,4)=Pv
NEXT P
!------
!リスト
PRINT "K=";K
PRINT "番号 周波数 E5 θ5"
FOR i=1 TO 57
PRINT USING "###": i;
PRINT USING " ###,###.#" : FREQ(i,1);
PRINT USING " ####.### dB": FREQ(i,2);
PRINT USING " ####.### 度": FREQ(i,4)
NEXT i
!------
!グラフ
FOR f=1 TO 6
SET TEXT COLOR "black"
PLOT TEXT ,AT f-0.1, 1:
mid$("10 100 1k 10k 100k ",4*(f-1)+1,4) !x軸
10Hz^100kHz
PLOT TEXT ,AT 0.8,-10*(f-1)-2:
mid$(" 0 -25 -50 -75 -100-125 ",4*(f-1)+1,4) !左y軸 0~-125dB
SET TEXT COLOR "red"
PLOT TEXT ,AT 5.1,-10*(f-1)-2:
mid$(" 0 -80 -160-240-320-400 ",4*(f-1)+1,4) !右y軸 0~-400°
NEXT f
SET LINE COLOR "black"
FOR i=1 TO 57
PLOT LINES:LOG10(FREQ(i,1)) ,FREQ(i,2)/2.5; !利得[dB]
NEXT i
PLOT LINES
SET LINE COLOR "red"
FOR i=1 TO 57
PLOT LINES:LOG10(FREQ(i,1)) ,0.125*FREQ(i,4); !位相角度[度]
NEXT i
PLOT LINES
NEXT K
!式(中置記法)の評価 - 1変数多項式の係数が整数の場合 ※UBASIC相当
DECLARE EXTERNAL SUB expr.eval
!LET s$="(x-2)*(x-3)*(x-4)*(x-5)"
LET s$="(x^2-2*x+3)^2"
!LET s$="(x^5-5*x^3+5*x^2-1)/(x^2+3*x+1)" !商 x^3-3*x^2+3*x-1、余り 0
!LET s$="mod(2*x^3-13*x^2-26*x-15,x^2-2*x+3)" !商 2*x-9、余り -50*x+12
!LET s$="gcd(3*x^2+5*x-2,3*x^2-7*x+2)" !12*x-4 { 3*x-1 }
!LET s$="lcm(3*x^2+5*x-2,3*x^2-7*x+2)" !3/4*x^3-1/4*x^2-3*x+1 { (x+2)*(x-2)*(3*x-1) }
!LET s$="lcm(x^3-16*x,x^3-8*x^2+16*x)"
DIM a(0 TO 8) !係数 a(n)*x^n+a(n-1)*x^(n-1)+ … +a(1)*x+a(0)
CALL eval(s$, a,rc) !式
MAT PRINT a; !x^0,x^1,x^2, … の順 debug
IF rc=0 THEN CALL poly_disp(a) !結果を表示する
END
MODULE expr
PUBLIC NUMERIC p,ErrNo !共通変数
!●解析部分
!下位の共通ルーチン
EXTERNAL FUNCTION token$(s$) !1文字読み込む
CALL EatSpace(s$)
IF p<=LEN(s$) THEN LET token$=s$(p:p) ELSE LET token$=""
END FUNCTION
EXTERNAL SUB EatSpace(s$) !空白を読み飛ばす
DO WHILE s$(p:p)=" " AND p<=LEN(s$)
LET p=p+1
LOOP
END SUB
EXTERNAL SUB CheckToken(s$,L$) !文字を確認する
CALL EatSpace(s$)
IF UCASE$(s$(p:p+LEN(L$)-1))<>L$ THEN CALL Error(L$&"がありません。")
LET p=p+LEN(L$) !eat it
END SUB
EXTERNAL SUB Error(x$) !メッセージを表示する
PRINT
PRINT x$; p
LET errNo=1
END SUB
!上位ルーチン
PUBLIC SUB eval
EXTERNAL SUB eval(s$, v(),rc) !式の評価
LET errNo=0 !エラーコード
LET p=1 !文字列へのポインタ
CALL expression(s$, v) !計算する
LET rc=errNo
END SUB
EXTERNAL SUB expression(s$, v()) !式
DIM w(0 TO UBOUND(v))
LET t$=token$(s$)
IF t$="-" THEN !符号なら
LET p=p+1 !eat it
CALL term(s$, v)
IF errNo<>0 THEN EXIT SUB
CALL op_neg(v, v) !v=-v
ELSE
IF t$="+" THEN LET p=p+1 !eat it
CALL term(s$, v)
END IF
IF errNo<>0 THEN EXIT SUB
LET t$=token$(s$)
DO WHILE t$="+" OR t$="-" !加算、減算なら
LET p=p+1 !eat it
CALL term(s$, w)
IF errNo<>0 THEN EXIT SUB
IF t$="+" THEN !計算する
CALL op_add(v,w, v) !v=v+w
ELSE
CALL op_sub(v,w, v) !v=v-w
END IF
IF errNo<>0 THEN EXIT SUB
LET t$=token$(s$) !次へ
LOOP
END SUB
EXTERNAL SUB term(s$, v()) !項
DIM w(0 TO UBOUND(v))
CALL factor(s$,v)
IF errNo<>0 THEN EXIT SUB
LET t$=token$(s$)
DO WHILE t$="*" OR t$="/" !乗算、除算なら
LET p=p+1 !eat it
CALL factor(s$,w)
IF errNo<>0 THEN EXIT SUB
IF t$="*" THEN !計算する
CALL op_mul(v,w, v) !v=v*w
ELSE
CALL op_div(v,w, v) !v=v/w
END IF
IF errNo<>0 THEN EXIT SUB
LET t$=token$(s$) !次へ
LOOP
END SUB
EXTERNAL SUB factor(s$, v()) !因子
DIM w(0 TO UBOUND(v))
LET t$=token$(s$)
IF t$="(" THEN !括弧なら
LET p=p+1 !eat it
CALL expression(s$,w) !式
IF errNo<>0 THEN EXIT SUB
MAT v=w
CALL CheckToken(s$,")") !閉じ括弧か確認する
ELSE
CALL num(s$,v)
END IF
IF errNo<>0 THEN EXIT SUB
LET t$=token$(s$)
DO WHILE t$="^" !べき乗なら
LET p=p+1 !eat it
LET t$=token$(s$)
IF t$="(" THEN !括弧なら
LET p=p+1 !eat it
CALL expression(s$,w) !式
IF errNo<>0 THEN EXIT SUB
CALL CheckToken(s$,")") !閉じ括弧か確認する
ELSE
CALL num(s$,w)
END IF
IF errNo<>0 THEN EXIT SUB
CALL op_pow(v,w, v) !計算する v=v^w
IF errNo<>0 THEN EXIT SUB
LET t$=token$(s$) !次へ
LOOP
END SUB
EXTERNAL SUB num(s$,v()) !数
DIM w(0 TO UBOUND(v)),x(0 TO UBOUND(v))
LET c=fnc(s$)
IF c>0 THEN !関数なら
LET t$=token$(s$)
IF t$="(" THEN !括弧なら
LET p=p+1 !eat it
CALL expression(s$,w) !引数1
IF errNo<>0 THEN EXIT SUB
MAT v=w
CALL CheckToken(s$,",") !カンマか確認する
CALL expression(s$,w) !引数2
IF errNo<>0 THEN EXIT SUB
IF c=1 THEN !modpow(a,n,b)形式
CALL CheckToken(s$,",") !カンマか確認する
CALL expression(s$,w) !引数3
IF errNo<>0 THEN EXIT SUB
MAT x=w
CALL set_fnc3(c,v,w,x, v) !v=fnc(v,w,x)
ELSE
CALL set_fnc2(c,v,w, v) !v=fnc(v,w)
END IF
IF errNo<>0 THEN EXIT SUB
CALL CheckToken(s$,")") !閉じ括弧か確認する
ELSE
CALL Error("不正な文字です。")
END IF
ELSE
LET c=var(s$)
IF c>0 THEN !変数なら
CALL set_var(c, v)
ELSE
LET c=number(s$)
IF c>=0 THEN !定数(数値)なら
CALL set_number(c, v)
ELSE
CALL Error("不正な文字です。")
END IF
END IF
END IF
END SUB
EXTERNAL FUNCTION fnc(s$) !関数
DATA "MODPOW","MODINV","MOD","GCD","LCM" !※文字長が大きい順
LET k=0
DO
LET k=k+1
READ IF MISSING THEN EXIT DO: d$
IF UCASE$(s$(p:p+LEN(d$)-1))=UCASE$(d$) THEN !一致したら
LET p=p+LEN(d$)
LET fnc=k
EXIT FUNCTION
END IF
LOOP
LET fnc=-1
END FUNCTION
EXTERNAL FUNCTION var(s$) !変数
LET t$=UCASE$(token$(s$)) !大文字へ
IF "A"<=t$ AND t$<="Z" THEN
!!!IF t$="X" THEN
LET p=p+1 !eat it
LET var=ORD(t$)-ORD("@") !オフセット @=0,A=1,B=2,…,Z=26
ELSE
LET var=-1
END IF
END FUNCTION
EXTERNAL FUNCTION number(s$) !数値(0、正の整数)
LET i0=p !先頭位置を記録する
LET t$=token$(s$)
DO WHILE t$>="0" AND t$<="9"
LET p=p+1
LET t$=token$(s$)
LOOP
LET number=-1
IF p>i0 THEN LET number=VAL(s$(i0:p-1)) !数字列の範囲を切り取る
END FUNCTION
!●演算部分 ※「数の組」に応じて演算を定義する
EXTERNAL SUB op_neg(v1(), v()) !符号(負)
MAT v=(-1)*v1
END SUB
EXTERNAL SUB op_add(v1(),v2(), v()) !加算
MAT v=v1+v2
END SUB
EXTERNAL SUB op_sub(v1(),v2(), v()) !減算
MAT v=v1-v2
END SUB
EXTERNAL SUB op_mul(v1(),v2(), v()) !乗算
LET N=UBOUND(v)
DIM w(0 TO N*2) !桁数は2倍になる
MAT w=ZER
FOR i=0 TO N !係数
FOR j=0 TO N
LET w(i+j)=w(i+j)+v1(i)*v2(j) !畳み込み
NEXT j
NEXT i
IF poly_degree(w)>N THEN CALL Error("オーバーフロー")
FOR i=0 TO N !下n桁をコピーする
LET v(i)=w(i)
NEXT i
END SUB
EXTERNAL SUB op_div(v1(),v2(), v()) !除算
DIM Q(0 TO UBOUND(v)),R(0 TO UBOUND(v))
IF poly_degree(v2)=0 AND v2(0)=0 THEN !定数の0なら
CALL Error("0では割れません。")
EXIT SUB
END IF
CALL poly_div(v1,v2, Q,R)
MAT v=Q !商 ※v=INT(v1/v2)に相当
END SUB
EXTERNAL SUB op_pow(v1(),v2(), v()) !べき算
DIM x(0 TO UBOUND(v)),T(0 TO UBOUND(v))
MAT x=v1 !x=v1
MAT T=ZER !定数1
LET T(0)=1
IF poly_degree(v1)=0 THEN !定数項のみ(定数)
IF poly_degree(v2)>0 THEN CALL Error("べき数は整数のみ")
IF errNo<>0 THEN EXIT SUB
IF v1(0)=0 AND v2(0)<0 THEN CALL Error("0の負べき乗")
IF errNo<>0 THEN EXIT SUB
LET v(0)=v1(0)^v2(0)
ELSE
IF poly_degree(v2)>0 OR v2(0)<0 THEN CALL Error("べき数は非負整数のみ")
IF errNo<>0 THEN EXIT SUB
LET m=v2(0)
DO UNTIL m=0
IF MOD(m,2)=1 THEN CALL op_mul(T,x, T) !ビットが1なら、T=T*x
IF errNo<>0 THEN EXIT SUB
CALL op_mul(x,x, x) !x=x^2
IF errNo<>0 THEN EXIT SUB
LET m=INT(m/2) !2進数にする
LOOP
MAT v=T
END IF
END SUB
EXTERNAL SUB set_fnc(c,v1(), v()) !関数(値)を設定する ※引数1個
!該当関数なし
END SUB
EXTERNAL SUB set_fnc2(c,v1(),v2(), v()) !関数(値)を設定する ※引数2個
LET N=UBOUND(v)
DIM Q(0 TO N),R(0 TO N),A(0 TO N),B(0 TO N)
SELECT CASE c !各関数に応じて
CASE 2 !modinv
PRINT "modinv関数は未サポート!"
CASE 3 !剰余
CALL poly_div(v1,v2, Q,R)
MAT v=R !余り
CASE 4,5 !最大公約数、最小公倍数
MAT A=v1
MAT B=v2
DO UNTIL poly_degree(B)=0 AND B(0)=0 !b=0
CALL poly_div(A,B, Q,R) !R=MOD(a,b)
MAT A=B !a=b
MAT B=R !b=R
LOOP
IF c=5 THEN !LCM=v1*v2/GCD(v1,v2)
CALL op_div(v1,A, Q)
IF errNo<>0 THEN EXIT SUB
CALL op_mul(Q,v2, v)
ELSE !GCD
MAT v=A
END IF
CASE ELSE
END SELECT
END SUB
EXTERNAL SUB set_fnc3(c,v1(),v2(),v3(), v()) !関数(値)を設定する ※引数3個
PRINT "modpow関数は未サポート!"
END SUB
EXTERNAL SUB set_var(c, v()) !変数(値)
MAT v=ZER
LET v(1)=1 !x^1の係数
END SUB
EXTERNAL SUB set_number(c, v()) !定数(数値)
MAT v=ZER
LET v(0)=c !x^0の係数
END SUB
END MODULE
!補助ルーチン
!演算関連
EXTERNAL SUB poly_div(A(),B(), Q(),R()) !除算 ※被除数=商*除数+余り
DIM w(0 TO UBOUND(A))
LET aa=poly_degree(A)
LET bb=poly_degree(B)
MAT Q=ZER !商、その次数
LET qq=MAX(aa-bb,0)
MAT R=A !余り、その次数
LET rr=aa
DO WHILE rr>=bb !被除数の次数が除数のより大きいなら
IF R(rr)<>0 THEN !係数が0以外なら
LET k=R(rr)/B(bb) !商の係数
LET Q(rr-bb)=k !商
MAT w=ZER !余り
FOR i=bb TO 0 STEP -1 !R=A-k*B ※筆算参照
LET w(rr-bb+i)=k*B(i)
NEXT i
MAT R=R-w
END IF
LET rr=rr-1 !次の次数へ
LOOP
END SUB
EXTERNAL FUNCTION poly_degree(v()) !次数を得る
FOR i=UBOUND(v) TO 1 STEP -1
IF v(i)<>0 THEN EXIT FOR !係数が0でない最初の位置
NEXT i
LET poly_degree=i
END FUNCTION
!表示関連
EXTERNAL SUB poly_disp(A()) !多項式を表示する a(X)=ΣAkX^k=AnX^n+An-1X^n-1+…+A1X+A0
LET aa=poly_degree(A) !最初の項
CALL mono_disp(A(aa),aa)
FOR i=aa-1 TO 0 STEP -1 !次項
LET w=A(i)
IF w>0 THEN PRINT "+";
IF w<>0 OR (w=0 AND aa=0) THEN CALL mono_disp(w,i)
NEXT i
END SUB
EXTERNAL SUB mono_disp(ak,k) !単項式を表示する Ak*X^k
IF k<>0 THEN !x^nで
IF ak=1 THEN !係数が1なら
ELSEIF ak=-1 THEN !係数が−1なら
PRINT "-";
ELSE
PRINT STR$(ak);"*";
END IF
END IF
IF k=0 THEN !次数が0なら
PRINT STR$(ak);
ELSEIF k=1 THEN !次数が1なら
PRINT "X";
ELSE
PRINT "X^";STR$(k);
END IF
END SUB
OPTION ANGLE DEGREES
OPTION ARITHMETIC COMPLEX
LET NP=3
LET rss=10 !14 周波数、10倍毎のステップ数
!
DIM FREQ(0 TO rss*4, 4), A(NP,NP), T(NP,NP), EOUT(NP,1), B(NP,1)
!----
! 周波数10Hz~100KHz、等比ステップ
FOR p=0 TO rss*4
LET FREQ(p,1)=10^(1+p/rss)
NEXT p
!----
! CR 3段回路
LET R1=51E3 !Ω
LET R2=82E3 !Ω 51E3 ! 以下、右側の数値でGv=100でも、ほぼ平坦に戻る。
LET R3=39E3 !Ω
LET C1=0.00685E-6 !F 0.0047E-6
LET C2=0.022E-6 !F 0.033E-6
LET C3=330E-12 !F 270E-12
!----
SET WINDOW 0.5,5.5, -55,5
DRAW grid(1,5)
!----
! 目盛り
FOR p=0 TO 5
SET TEXT COLOR "black"
PLOT TEXT ,AT p+0.9,
1 :mid$("10 100 1k 10k
100k", 4*p+1, 4) !x軸 10Hz~100kHz
PLOT TEXT ,AT 0.7,-10*p-2 :mid$(" 0 -25 -50 -75 -100-125", 4*p+1, 4)!y軸 0~-125dB 左
SET TEXT COLOR "red"
PLOT TEXT ,AT 5.1,-10*p-2 :mid$(" 0 -80 -160-240-320-400", 4*p+1, 4)!y軸 0~-400°右
NEXT p
!----
FOR Gv=10 TO 100 STEP 10
LET K=Gv/(1+Gv)
PRINT USING "Gv=### K=.####" :Gv, K
PRINT "番号 周波数 E5 θ5"
!----
FOR p=0 TO rss*4
LET ω=2*PI*FREQ(p,1)
!
LET A(1,1)= 1/R1+1/R2+COMPLEX(0,ω*C1)
LET A(1,2)=-1/R2
LET A(1,3)=0
LET A(2,1)=-1/R2
LET A(2,2)= 1/R2+1/R3+COMPLEX(0,ω*C2)
LET A(2,3)=-1/R3-K*COMPLEX(0,ω*C2)
LET A(3,1)=0
LET A(3,2)=-1/R3
LET A(3,3)= 1/R3+COMPLEX(0,ω*C3)
!
LET Vin=1
LET B(1,1)=Vin/R1
LET B(2,1)=0
LET B(3,1)=0
!
MAT T=INV(A)
MAT EOUT=T*B
!
LET Af=K*EOUT(3,1)/Vin
LET Pf=arg(Af)
IF Pf>0 THEN LET Pf=Pf-360
LET FREQ(p,2)=20*LOG10(ABS(Af))
LET FREQ(p,4)=Pf
!------
!リスト
PRINT USING "### ###,###.# ####.### dB ####.### 度": p, FREQ(p,1), FREQ(p,2), FREQ(p,4)
!------
!グラフ
IF 0<p THEN
SET LINE COLOR "black"
PLOT
LINES:LOG10(FREQ(p-1,1)),0.4*FREQ(p-1,2);
LOG10(FREQ(p,1)),0.4*FREQ(p,2) !利得[dB]
SET LINE COLOR "red"
PLOT
LINES:LOG10(FREQ(p-1,1)),0.125*FREQ(p-1,4);
LOG10(FREQ(p,1)),0.125*FREQ(p,4) !位相[度]
END IF
NEXT p
NEXT Gv
OPTION ANGLE DEGREES
OPTION ARITHMETIC COMPLEX
LET NP=3
LET rss=10 !14 周波数、10倍毎のステップ数
!
DIM FREQ(0 TO rss*4, 4), A(NP,NP), T(NP,NP), IOUT(NP,1), B(NP,1)
!----
! 周波数10Hz~100KHz、等比ステップ
FOR p=0 TO rss*4
LET FREQ(p,1)=10^(1+p/rss)
NEXT p
!----
! CR 3段回路 ! (Gv=1000000) ! (Gv=100)
LET R1=51E3 !Ω
LET R2=51E3 !Ω 82E3 ! 51E3
LET R3=39E3 !Ω
LET C1=0.0047E-6 !F 0.00685E-6 ! 0.0047E-6
LET C2=0.033E-6 !F 0.022E-6 ! 0.033E-6
LET C3=270E-12 !F 330E-12 ! 270E-12
!----
SET WINDOW 0.5,5.5, -55,5
DRAW grid(1,5)
!----
! 目盛り
FOR p=0 TO 5
SET TEXT COLOR "black"
PLOT TEXT ,AT p+0.9,
1 :mid$("10 100 1k 10k
100k", 4*p+1, 4) !x軸 10Hz~100kHz
PLOT TEXT ,AT 0.7,-10*p-2 :mid$(" 0 -25 -50 -75 -100-125", 4*p+1, 4)!y軸 0~-125dB 左
SET TEXT COLOR "red"
PLOT TEXT ,AT 5.1,-10*p-2 :mid$(" 0 -80 -160-240-320-400", 4*p+1, 4)!y軸 0~-400°右
NEXT p
!----
FOR Gv=10 TO 100 STEP 10
LET K=Gv/(1+Gv)
PRINT USING "Gv=### K=.####" :Gv, K
PRINT "番号 周波数 Vout/Vin θ"
!----
FOR p=0 TO rss*4
LET ω=2*PI*FREQ(p,1)
!
LET A(1,1)= R1+1/COMPLEX(0,ω*C1)
LET A(1,2)=-1/COMPLEX(0,ω*C1)
LET A(1,3)=0
LET A(2,1)=-1/COMPLEX(0,ω*C1)
LET A(2,2)= 1/COMPLEX(0,ω*C1)+R2+R3+1/COMPLEX(0,ω*C3)
LET A(2,3)= R3+1/COMPLEX(0,ω*C3)
LET A(3,1)=0
LET A(3,2)= R3+1/COMPLEX(0,ω*C3)-K/COMPLEX(0,ω*C3)
LET A(3,3)=1/COMPLEX(0,ω*C2)+R3+1/COMPLEX(0,ω*C3)-K/COMPLEX(0,ω*C3)
!
LET Vin=1
LET B(1,1)=Vin
LET B(2,1)=0
LET B(3,1)=0
!
MAT T=INV(A)
MAT IOUT=T*B
!
LET Af=K*((IOUT(2,1)+IOUT(3,1))/COMPLEX(0,ω*C3))/Vin
LET Pf=arg(Af)
IF Pf>0 THEN LET Pf=Pf-360
LET FREQ(p,2)=20*LOG10(ABS(Af))
LET FREQ(p,4)=Pf
!------
!リスト
PRINT USING "### ###,###.# ####.### dB ####.### 度": p, FREQ(p,1), FREQ(p,2), FREQ(p,4)
!------
!グラフ
IF 0< p THEN
SET LINE COLOR "black"
PLOT
LINES:LOG10(FREQ(p-1,1)),0.4*FREQ(p-1,2);
LOG10(FREQ(p,1)),0.4*FREQ(p,2) !利得[dB]
SET LINE COLOR "red"
PLOT
LINES:LOG10(FREQ(p-1,1)),0.125*FREQ(p-1,4);
LOG10(FREQ(p,1)),0.125*FREQ(p,4) !位相[度]
END IF
NEXT p
NEXT Gv
! i3 逆方向の、差し替え部分( 左端!を外して使用。)
! LET A(1,1)= R1+1/COMPLEX(0,ω*C1)
! LET A(1,2)=-1/COMPLEX(0,ω*C1)
! LET A(1,3)= 0
! LET A(2,1)=-1/COMPLEX(0,ω*C1)
! LET A(2,2)= 1/COMPLEX(0,ω*C1)+R2+R3+1/COMPLEX(0,ω*C3)
! LET A(2,3)=-R3-1/COMPLEX(0,ω*C3)
! LET A(3,1)= 0
! LET A(3,2)=-R3-1/COMPLEX(0,ω*C3)+K/COMPLEX(0,ω*C3)
! LET A(3,3)= 1/COMPLEX(0,ω*C2)+R3+1/COMPLEX(0,ω*C3)-K/COMPLEX(0,ω*C3)
! !
! LET Vin=1
! LET B(1,1)=Vin
! LET B(2,1)=0
! LET B(3,1)=0
! !
! MAT T=INV(A)
! MAT IOUT=T*B
! !
! LET Af=K*((IOUT(2,1)-IOUT(3,1))/COMPLEX(0,ω*C3))/Vin
!ここまで
!
SET TEXT BACKGROUND "OPAQUE"
OPTION ARITHMETIC COMPLEX
LET N=3
DIM A(N),Xr(N)
!
LET R=12E3 !Ω
LET C=0.0033E-6 !F
LET RC=R*C
!------------------
! z y で表示する( 山中氏の3DプロットSUB)
! │/
! ・─x
!------------------
SUB rotx(x,y,z,a)
LET w=y*COS(a)-z*SIN(a)
LET z=y*SIN(a)+z*COS(a)
LET y=w
END SUB
SUB rotz(x,y,z,a)
LET w=x*COS(a)-y*SIN(a)
LET y=x*SIN(a)+y*COS(a)
LET x=w
END SUB
SUB plots(x,y,z)
CALL rotz(x,y,z,-PI/2.5)
CALL rotx(x,y,z,-PI/10)
PLOT LINES:x,y;
END SUB
SUB plott(x,y,z,w$)
CALL rotz(x,y,z,-PI/2.5)
CALL rotx(x,y,z,-PI/10)
PLOT TEXT,AT x,y:w$
END SUB
!------------------
SET WINDOW -4.2,3.7, -3.6,4.3
!-----
! 目盛り
FOR x=-2 TO 1
IF x=0 THEN SET LINE STYLE 1 ELSE SET LINE STYLE 3
CALL plots((x),-3, 0)
CALL plots((x),+3, 0) ! (x) は、SUB からxの書き戻しの防止。
PLOT LINES
CALL plott(x-.1, -3.7, 0, USING$("######",x*5000) )
NEXT x
FOR y=-3 TO 3
IF y=0 THEN SET LINE STYLE 1 ELSE SET LINE STYLE 3
CALL plots(-2,(y), 0)
CALL plots( 1,(y), 0)
PLOT LINES
CALL plott(1.3, y-.3, 0, STR$(y*5000)&"j" )
CALL plott(1.6, y-.4, 0, USING$("#####",y*5000/(2*PI))&"Hz" )
NEXT y
SET LINE STYLE 1
!----
SET LINE COLOR 1
CALL plots(-2,0,0)
CALL plots(-2,0,4)
PLOT LINES
CALL plott(-2, 0.1, 1.5, "K=0.90" )
CALL plott(-2, 0.1, 2.5, "K=0.95" )
CALL plott(-2, 0.1, 3.5, "K=1.0" )
!
!-----
! K と根のグラフ
LET rss=15 ! Gv=10~100000 10倍毎のステップ数
FOR p=0 TO 4*rss
LET Gv=10^(1+p/rss)
LET K=Gv/(1+Gv)
!
LET A(1)=6*(1-K)/RC
LET A(2)=5*(1-K)/RC^2
LET A(3)=(1-K)/RC^3
CALL DKA_00
!
PRINT USING "Gv=###### K=.#####": Gv,K;
FOR s=1 TO 3
PRINT USING"┃#####.# #####.#Hz" :re(Xr(s)),im(Xr(s))/(2*PI);
SET LINE COLOR s+1
CALL plots(re(Xr(s))/5000,im(Xr(s))/5000, 0)
CALL plots(re(Xr(s))/5000,im(Xr(s))/5000,(K-0.8)*20)
PLOT LINES
NEXT s
PRINT
NEXT p
! Xr( 1 ~ n ) <== root
!--------------------------------------------
SUB DKA_00
LET r=1
FOR j=2 TO N
LET rn=ABS(A(j))^(1/j)
if r<rn then LET r=rn
NEXT j
FOR j=1 TO N
LET Xr(j)=-A(1)/N+r*EXP( complex(0,1)*2*PI/N *(j-3/4) )
NEXT j
FOR m=0 TO 100
LET mfx=0
LET maj=0
FOR j=1 TO N
LET Xk=1
LET fx=1
FOR w=1 TO N
LET fx=fx*Xr(j)+A(w)
IF w<>j THEN LET Xk=Xk*(Xr(j)-Xr(w))
NEXT w
LET Xr(j)=Xr(j)-fx/Xk
IF mfx<ABS(fx) THEN LET mfx=ABS(fx)
IF maj<ABS(fx/Xk) THEN LET maj=ABS(fx/Xk)
NEXT j
IF mfx<.0000001 AND maj<.0000001 THEN EXIT FOR
NEXT m
END SUB
LET N=4 !次数
DIM A(0 TO N) !多項式の係数 A(n)*s^n+A(n-1)*s^(n-1)+ … +A(1)*s+A(0)、A(n)>0
DATA 1,5,10,10,4 !s^4+5*s^3+10*s^2+10*s+4
FOR i=N TO 0 STEP -1
READ A(i) !係数を読み込む
IF A(i)<=0 THEN !すべて正かどうか確認する
PRINT "安定な多項式でない。"
STOP
END IF
NEXT i
!ラウス表をつくる
!1行 B1 A(N) A(N-2) A(N-4) …
!2行 B2 A(N-1) A(N-3) A(N-5) … → B1
!3行 B3 → B2
! : → B3
! :
LET M=INT(N/2)
DIM B1(0 TO M),B2(0 TO M),B3(0 TO M)
FOR i=0 TO N !0行目、1行目
IF MOD(i,2)=0 THEN LET B1(INT(i/2))=A(N-i) ELSE LET B2(INT(i/2))=A(N-i)
NEXT i
MAT PRINT B1; !debug
MAT PRINT B2;
FOR l=2 TO N !2行目〜N行目
MAT B3=ZER
FOR i=0 TO M-1
LET B3(i)=-1/B2(0)*( B1(0)*B2(i+1) - B1(i+1)*B2(0) )
NEXT i
MAT PRINT B3; !debug
IF B3(0)<=0 THEN !ラウス数列がすべて正かどうか確認する
PRINT "安定な多項式でない。"
STOP
END IF
MAT B1=B2
MAT B2=B3
NEXT l
PRINT "安定な多項式である。"
END
●フルビッツ(Hurwitz)の安定判別法
LET N=4 !次数
DIM A(0 TO N) !多項式の係数 A(n)*s^n+A(n-1)*s^(n-1)+ … +A(1)*s+A(0)
DATA 1,5,10,10,4 !s^4+5*s^3+10*s^2+10*s+4
FOR i=N TO 0 STEP -1
READ A(i) !係数を読み込む
IF A(i)<=0 THEN !すべて正かどうか確認する
PRINT "安定な多項式でない。"
STOP
END IF
NEXT i
!フルビッツ行列式をつくる
!│A(n-1) A(n-3) A(n-5) … 0 │
!│A(n) A(n-2) A(n-4) … 0 │
!│0 A(n-1) A(n-3) … 0 │
!│0 A(n) A(n-2) … 0 │
! :
! :
!│0 0 0 … A(1)│
DIM B(N,N)
FOR m=1 TO N
MAT B=ZER(m,m)
LET k=N-1
FOR i=1 TO m
FOR j=1 TO m
LET t=k-2*(j-1)
IF t>=0 AND t<=N THEN LET B(i,j)=A(t)
NEXT j
LET k=k+1
NEXT i
MAT PRINT B; !debug
IF DET(B)<=0 THEN
PRINT "不安定な多項式です。"
!STOP
END IF
PRINT "行列式=";DET(B) !debug
NEXT m
PRINT "安定な多項式である。"
END
!1入力1出力、状態変数がN個の1階の連立微分方程式
! 状態方程式 x'(t)=A*x(t)+b*u(t) ※A:N×N、b:N×1
! 出力方程式 y(t)=C*x(t) ※C:1×N
!から
! 伝達関数 G(s)=c*INV(s*I-A)*b=c*adj(s*I-A)*b/det(s*I-A)
!を求める
!行列関連
FUNCTION tr(A(,)) !行列Aのトレース
LET t=0
FOR i=1 TO N
LET t=t+A(i,i)
NEXT i
LET tr=t
END FUNCTION
!多項式関連
SUB mono_disp(ak,k) !単項式を表示する Ak*X^k
IF k<>0 THEN !x^nで
IF ak=1 THEN !係数が1なら
ELSEIF ak=-1 THEN !係数が−1なら
PRINT "-";
ELSE
PRINT STR$(ak);"*";
END IF
END IF
IF k=0 THEN !次数が0なら
PRINT STR$(ak);
ELSEIF k=1 THEN !次数が1なら
PRINT "s";
ELSE
PRINT "s^";STR$(k);
END IF
END SUB
!-------------------- ここまでがサブルーチン
!---------- ↓↓↓↓↓ ----------
LET N=3 !状態変数の数
DATA 0,0,-6 !A
DATA 1,0,-11
DATA 0,1,-6
DATA 1 !b
DATA 0
DATA 0
DATA 0,0,1 !c
!---------- ↑↑↑↑↑ ----------
DIM A(N,N),b(N,1),c(1,N)
MAT READ A
MAT READ b
MAT READ c
!Frame法、Leverrir-Faddeev法
! adj(s*I-A)=s^(n-1)*I+s^(n-2)*β1+ … +s*βn-2+βn-1
! det(s*I-A)=s^n+α1*s^(n-1)+ … + αn-1*s+αn
!のとき
! β0=I、k=1〜nについて
! Xk=A*βk-1
! αk=-trace(Xk)/k
! βk=Xk+αk*I
!の逐次計算でαk、βkが求まる。
DIM c1(N) !多項式 c(1)*X^(N-1)+c(2)*X^(N-2)+ … +c(N-1)*X+c(N) の係数
DIM c2(N) !多項式 X^N+c(1)*X^(N-1)+c(2)*X^(N-2)+ … +c(N-1)*X+c(N) の係数
DIM X(N,N),sE(N,N),T1(1,N),T2(1,1) !作業用
MAT X=IDN !adj(s*I-A)
FOR k=1 TO N
!!!MAT PRINT X; !debug
MAT T1=c*X !c*adj(s*I-A)*b ※定数*多項式*定数
MAT T2=T1*b
LET c1(k)=T2(1,1)
MAT X=A*X
LET c2(k)=-tr(X)/k !det(s*I-A)
MAT sE=(c2(k))*IDN
MAT X=X+sE
NEXT k
!!!MAT PRINT c1; !debug
PRINT "分子= ";
FOR i=1 TO N !分子側の多項式を表示する
LET w=c1(i)
IF w>0 THEN PRINT "+";
IF w<>0 THEN CALL mono_disp(w,N-i)
NEXT i
PRINT
!!!MAT PRINT c2; !debug
PRINT "分母= ";
CALL mono_disp(1,N) !分母側の多項式を表示する
FOR i=1 TO N
LET w=c2(i)
IF w>0 THEN PRINT "+";
IF w<>0 THEN CALL mono_disp(w,N-i)
NEXT i
END
OPTION ARITHMETIC RATIONAL
LET N=20
PRINT fact(N) !検算
LET A=N
LET S=0 !5の数を数える
DO UNTIL A=0
LET A=INT(A/5) !5,5^2,5^3,…で割る
LET S=S+A
LOOP
PRINT S;"個"
!LET A=N
!LET S=0 !2の数を数える
!DO UNTIL A=0
! LET A=INT(A/2) !2,2^2,2^3,…で割る
! LET S=S+A
!LOOP
!PRINT S;"個"
END
●n!の素因数分解
2〜nまでの素数で、それぞれの個数を求める。(上記を利用する)
LET N=20
FOR i=2 TO N
IF isPRIME(i)=-1 THEN !素数に対して
LET a=N
LET s=0 !素数iの個数
DO UNTIL a=0
LET a=INT(a/i)
LET s=s+a
LOOP
PRINT STR$(i);"^";STR$(s) !べき乗で表示
END IF
NEXT i
END
!●素数かどうか判定する(エラトステネスのふるい法)
! 変数 N: 判定する数値。※2以上
! 関数値:k>0 素数でない(kは約数)、-1 素数
EXTERNAL FUNCTION isPRIME(N)
IF MOD(N,2)=0 THEN !2で割り切れるなら素数でない
LET isPRIME=2
IF N=2 THEN LET isPRIME=-1 !2は素数
ELSE
LET isPRIME=-1 !素数である
FOR i=3 TO SQR(N) STEP 2 !Nの平方根までの奇数で繰り返す
!!!FOR i=3 TO INTSQR(N) STEP 2 !Nの平方根までの奇数で繰り返す
IF MOD(N,i)=0 THEN !iで割り切れるなら素数でない
LET isPRIME=i
EXIT FOR
END IF
NEXT i
END IF
END FUNCTION
●n!の計算
数の並びの対称性を利用する。
! 10!=1*2*3*4*5*6*7*8*9*10の場合
! 中央値 m=6
! 5と7 (m-1)*(m+1)=m^2-1=36-1=35、d=1
! 4と8 (m-2)*(m+2)=m^2-4=(m^2-1)-3=35-3=32、d=3
! 3と9 (m-3)*(m+3)=m^2-9=(m^2-4)-5=32-5=27、d=5
! 2と10 (m-4)*(m+4)=m^2-16=(m^2-9)-7=27-7=20、d=7
! 1 無視
! ∴10!=6*35*32*27*20
LET N=10
LET m=INT(N/2+1) !中央値
LET s=m
LET mm=m*m
LET d=1
FOR i=1 TO N-m
LET mm=mm-d
LET s=s*mm
LET d=d+2 !1,3,5,7,… 奇数
NEXT i
PRINT s
END
!Parabola Mandala(幾何学アート)
OPTION ANGLE DEGREES
SUB circle(a,b,r)
FOR t=0 TO 360
PLOT LINES: a+r*COS(t),b+r*SIN(t);
NEXT t
PLOT LINES
END SUB
DEF f(x)=x^2-x
LET c=(2*SQR(2))
LET d=(12*SQR(2))/5
LET e=(4-c)
LET g=24/5
LET h=(SQR(2)-1)
DIM M(4,4)!図形の裏返し
MAT READ M
DATA 0, 1, 0, 0
DATA 1, 0, 0, 0
DATA 0, 0, 1, 0
DATA 0, 0, 0, 1
!Lotus Mandala(右側の曼荼羅)
SET BITMAP SIZE 800,400
SET WINDOW -6.8,6.8,-6.8,6.8
SET VIEWPORT 0.5,1.0,0,0.5
CALL circle(0,0,c)
CALL circle(d,-d,e)
CALL circle(-d,d,e)
CALL circle(d,d,e)
CALL circle(-d,-d,e)
CALL circle(0,g,e)
CALL circle(0,-g,e)
CALL circle(g,0,e)
CALL circle(-g,0,e)
DRAW nike
DRAW nike WITH ROTATE(90)
DRAW nike WITH ROTATE(180)
DRAW nike WITH ROTATE(270)
DRAW nike WITH M
DRAW nike WITH M*ROTATE(90)
DRAW nike WITH M*ROTATE(180)
DRAW nike WITH M*ROTATE(270)
DRAW pothos WITH SCALE(h)*SHIFT(d,-d)
DRAW pothos WITH SCALE(h)*ROTATE(180)*SHIFT(-d,d)
DRAW pothos WITH SCALE(h)*ROTATE(90)*SHIFT(d,d)
DRAW pothos WITH SCALE(h)*ROTATE(270)*SHIFT(-d,-d)
DRAW pothos WITH M*SCALE(h)*ROTATE(180)*SHIFT(0,g)
DRAW pothos WITH M*SCALE(h)*SHIFT(0,-g)
DRAW pothos WITH M*SCALE(h)*ROTATE(90)*SHIFT(g,0)
DRAW pothos WITH M*SCALE(h)*ROTATE(270)*SHIFT(-g,0)
!Pothos Mandala(左側の曼荼羅)
SET BITMAP SIZE 800,400
SET WINDOW -6.8,6.8,-6.8,6.8
SET VIEWPORT 0,0.5,0,0.5
CALL circle(0,0,c)
CALL circle(d,-d,e)
CALL circle(-d,d,e)
CALL circle(d,d,e)
CALL circle(-d,-d,e)
CALL circle(0,g,e)
CALL circle(0,-g,e)
CALL circle(g,0,e)
CALL circle(-g,0,e)
DRAW pothos
DRAW pothos WITH SCALE(h)*SHIFT(d,-d)
DRAW pothos WITH SCALE(h)*ROTATE(180)*SHIFT(-d,d)
DRAW pothos WITH SCALE(h)*ROTATE(90)*SHIFT(d,d)
DRAW pothos WITH SCALE(h)*ROTATE(270)*SHIFT(-d,-d)
DRAW pothos WITH M*SCALE(h)*ROTATE(180)*SHIFT(0,g)
DRAW pothos WITH M*SCALE(h)*SHIFT(0,-g)
DRAW pothos WITH M*SCALE(h)*ROTATE(90)*SHIFT(g,0)
DRAW pothos WITH M*SCALE(h)*ROTATE(270)*SHIFT(-g,0)
PICTURE nike
FOR x=0 TO 2 STEP 0.01
PLOT LINES: x,f(x);
NEXT x
FOR x=9/4 TO 1/4 STEP -0.01
PLOT LINES: x-1/4,f(x)-13/16;
NEXT x
END PICTURE
PICTURE pothos
FOR y=-2 TO 1 STEP 0.01
PLOT LINES: -f(ABS(y)),y;
NEXT y
FOR x=-1/4 TO -9/4 STEP -0.01
PLOT LINES: x+1/4,SGN(x)*f(ABS(x))+13/16;
NEXT x
FOR x=-2 TO 2 STEP 0.01
PLOT LINES: x,SGN(x)*f(ABS(x));
NEXT x
END PICTURE
END
!Heart Magic(幾何学アート)
OPTION ANGLE DEGREES
DEF f(x)=x^2-x
DEF g(x)=-x^2-x
DEF h(x)=-x^2+1/2*x+1
DEF i(y)=y^2-y
DEF j(y)=y^2+1/2*y-1
DEF k(y)=y^2-1/2*y-1
DEF l(y)=-y^2+1/2*y+1
DIM M(4,4)
MAT READ M !図形の裏返し
DATA 0, 1, 0, 0
DATA 1, 0, 0, 0
DATA 0, 0, 1, 0
DATA 0, 0, 0, 1
SET WINDOW -9.2,9.2,-9.2,9.2
!集合
FOR n=6.9 TO 0 STEP -0.01
SET DRAW mode hidden
CLEAR
DRAW pothos WITH M*ROTATE(180)*SHIFT(0,n)
DRAW pothos WITH M*SHIFT(0,-n)
DRAW pothos WITH M*ROTATE(90)*SHIFT(n,0)
DRAW pothos WITH M*ROTATE(270)*SHIFT(-n,0)
DRAW pothos WITH SHIFT(n,-n)
DRAW pothos WITH ROTATE(180)*SHIFT(-n,n)
DRAW pothos WITH ROTATE(90)*SHIFT(n,n)
DRAW pothos WITH ROTATE(270)*SHIFT(-n,-n)
WAIT DELAY 0.01
SET DRAW mode explicit
NEXT n
WAIT DELAY 8
!発散
FOR n=0 TO 6.9 STEP 0.01
SET DRAW mode hidden
CLEAR
DRAW heart1 WITH SHIFT(-n,n)
DRAW heart1 WITH ROTATE(180)*SHIFT(-n/3,n)
DRAW heart1 WITH M*SHIFT(n/3,n)
DRAW heart1 WITH ROTATE(90)*SHIFT(n,n)
DRAW heart2 WITH SHIFT(-n,n/3)
DRAW heart2 WITH ROTATE(180)*SHIFT(-n/3,n/3)
DRAW heart2 WITH ROTATE(90)*SHIFT(n/3,n/3)
DRAW heart2 WITH ROTATE(270)*SHIFT(n,n/3)
DRAW heart3 WITH SHIFT(-n,-n/3)
DRAW heart3 WITH ROTATE(180)*SHIFT(-n/3,-n/3)
DRAW heart3 WITH ROTATE(90)*SHIFT(n/3,-n/3)
DRAW heart3 WITH ROTATE(270)*SHIFT(n,-n/3)
DRAW heart3 WITH M*ROTATE(180)*SHIFT(-n,-n)
DRAW heart3 WITH M*SHIFT(-n/3,-n)
DRAW heart3 WITH M*ROTATE(90)*SHIFT(n/3,-n)
DRAW heart3 WITH M*ROTATE(270)*SHIFT(n,-n)
WAIT DELAY 0.01
SET DRAW mode explicit
NEXT n
PICTURE heart1
FOR x=-1 TO 1 STEP 0.01
PLOT LINES: x,f(ABS(x));
NEXT x
FOR y=0 TO (1+SQR(17))/4 STEP 0.01
PLOT LINES: l(y),y;
NEXT y
FOR y=(1+SQR(17))/4 TO 0 STEP -0.01
PLOT LINES: k(y),y;
NEXT y
END PICTURE
PICTURE heart2
FOR x=-1 TO 0 STEP 0.01
PLOT LINES: x,g(x);
NEXT x
FOR y=0 TO 1 STEP 0.01
PLOT LINES: i(y),y;
NEXT y
FOR x=0 TO 2 STEP 0.01
PLOT LINES: x,h(x);
NEXT x
FOR y=-2 TO 0 STEP 0.01
PLOT LINES: j(y),y;
NEXT y
END PICTURE
PICTURE heart3
FOR y=-2 TO 1 STEP 0.01
PLOT LINES: -f(ABS(y)),y;
NEXT y
FOR x=-1/4 TO -9/4 STEP -0.01
PLOT LINES: x+1/4,SGN(x)*f(ABS(x))+13/16;
NEXT x
END PICTURE
PICTURE pothos
FOR y=-2 TO 1 STEP 0.01
PLOT LINES: -f(ABS(y)),y;
NEXT y
FOR x=-1/4 TO -9/4 STEP -0.01
PLOT LINES: x+1/4,SGN(x)*f(ABS(x))+13/16;
NEXT x
FOR x=-2 TO 2 STEP 0.01
PLOT LINES: x,SGN(x)*f(ABS(x));
NEXT x
END PICTURE
END
LET N=3 !次数
DIM A(0 TO N),B(0 TO N-1) !係数
DATA 6,-1,-3 !分子 6*x^2-x-3
DATA 1,0,-1,0 !分母 x^3-x=x*(x+1)*(x-1)
DATA 0,1 !根,重複度
DATA -1,1
DATA 1,1
!DATA 0,1,1 !分子 s+1
!DATA 1,-5,8,-4 !分母 s^3-5*s^2+8*s-4=(s-1)*(s-2)^2
!DATA 1,1 !根,重複度
!DATA 2,2
FOR i=N-1 TO 0 STEP -1
READ B(i)
NEXT i
FOR i=N TO 0 STEP -1
READ A(i)
NEXT i
!ヘヴィサイド(Heaviside)の展開定理
! F(x)=B(x)/A(x)とする。
! x-αが分母A(x)の重複度1の因数とすると
! 部分分数 C/(x-α) の係数は、C=(x-α)*F(x)│x=αとなる。
!
! x-αが分母A(x)の重複度mの因数とすると
! 部分分数 C1/(x-α)+C2/(x-α)^2+ … +Cm/(x-α)^m の係数は、
! Cm-k=1/k!*d^k/dx^k{(x-α)^m*F(x)}│x=α、k=0,1,2,…,m-1となる。
DIM Q(0 TO N),T1(0 TO 4*N),T2(0 TO 4*N) !作業用
DIM AA(0 TO 2*N),BB(0 TO 2*N),dA(0 TO 2*N),dB(0 TO 2*N)
LET Lp=N
DO WHILE Lp>0 !各根に対して
READ v,m !α、重複度
SELECT CASE m
CASE 1 !単根なら
CALL poly_divByLin(A,v, Q,R) !(x-α)*F(x)=B(x)/(A(x)/(x-α))
CALL PrintOut(B,Q,0,v)
CASE ELSE !重複根なら
MAT AA=A
MAT BB=B
FOR j=1 TO m !(x-α)^m*F(x)の0階微分
CALL poly_divByLin(AA,v, Q,R) !(x-α)^m*F(x)=B(x)/(A(x)/(x-α)^m)
MAT AA=Q
NEXT j
CALL PrintOut(BB,AA,m,v) !Cm
FOR k=1 TO m-1 !k階微分
!微分の公式 (B/A)'=(B'*A-B*A')/A^2
CALL poly_diff(BB, dB) !B'
CALL poly_diff(AA, dA) !A'
CALL poly_mul(dB,AA, T1) !分子
CALL poly_mul(BB,dA, T2)
MAT T1=T1-T2
CALL poly_copy(T1, BB)
CALL poly_mul(AA,AA, T1) !分母
CALL poly_copy(T1, AA)
CALL PrintOut(BB,AA,m-k,v/fact(k)) !Cm-k
NEXT k
END SELECT
LET Lp=Lp-m !次へ
LOOP
SUB PrintOut(B(),A(),k,v) !分数を表示する
PRINT poly_val(B,v)/poly_val(A,v); !分子側=C
IF v>0 THEN !分母側=x-α
PRINT "/ ( x -";v;")";
ELSEIF v<0 THEN
PRINT "/ ( x +";ABS(v);")";
ELSE
PRINT "/ x ";
END IF
IF k>1 THEN PRINT " ^";k ELSE PRINT !べき乗
END SUB
END
!補助ルーチン
!変数xの多項式 Σ[k=0,n]a(k)*x^k=a(n)*x^n+a(n-1)*x^(n-1)+ … +a(1)*x+a(0)
!演算関連
EXTERNAL FUNCTION poly_degree(A()) !次数を得る
FOR i=UBOUND(A) TO 1 STEP -1
IF A(i)<>0 THEN EXIT FOR !係数が0でない最初の位置
NEXT i
LET poly_degree=i
END FUNCTION
EXTERNAL SUB poly_divByLin(A(),v, Q(),R) !多項式a(x)をx-αで割ったときの商q(x)と余りRを求める
MAT Q=ZER
LET aa=poly_degree(A) !次数
IF aa>0 THEN !1次式以上なら
LET qq=aa-1 !次数
LET Q(qq)=A(aa) !商 ※組立除法
FOR i=qq TO 1 STEP -1
LET Q(i-1)=A(i)+Q(i)*v
NEXT i
LET R=A(0)+Q(0)*v !余り
ELSE
LET Q(0)=0 !商
LET R=A(0) !余り
END IF
END SUB
EXTERNAL FUNCTION poly_val(A(),v) !多項式を計算する(数値代入)
LET k=0
FOR i=UBOUND(A) TO 0 STEP -1 !Hornerの方法
LET k=k*v+A(i) !(…(((An*X+An-1)*X+An-2)*X+An-3)*X+…+A1)*X+A0
NEXT i
LET poly_val=k
END FUNCTION
EXTERNAL SUB poly_copy(A(), S()) !代入 S=A
MAT S=ZER
FOR i=0 TO UBOUND(S)
LET S(i)=A(i)
NEXT i
END SUB
EXTERNAL SUB poly_mul(A(),B(), S()) !乗算 S=A*B ※S≠A、S≠B
MAT S=ZER
FOR i=UBOUND(A) TO 0 STEP -1
FOR j=UBOUND(B) TO 0 STEP -1
LET S(i+j)=S(i+j)+A(i)*B(j) !すべての係数をかける
NEXT j
NEXT i
END SUB
EXTERNAL SUB poly_diff(A(), S()) !微分 S=A'
FOR i=1 TO UBOUND(A)
LET S(i-1)=i*A(i)
NEXT i
END SUB
LET N=3 !次数
DIM A(0 TO N),B(0 TO N-1) !係数
!DATA 6,-1,-3 !分子 6*x^2-x-3
!DATA 1,0,-1,0 !分母 x*(x^2-1)
!DATA 0,1 !根,重複度
!DATA -1,1
!DATA 1,1
DATA 0,1,1 !分子 s+1
DATA 1,-5,8,-4 !分母 s^3-5*s^2+8*s-4=(s-1)*(s-2)^2
DATA 1,1 !根,重複度
DATA 2,2
FOR i=N-1 TO 0 STEP -1
READ B(i)
NEXT i
FOR i=N TO 0 STEP -1
READ A(i)
NEXT i
DIM C(N,N),k(N) !連立方程式 C*k=B
DIM Q(0 TO N) !分母がx-αkの(通分したときの)分子側の係数
DIM AA(0 TO N),v(N),m(N)
LET Lp=1
DO UNTIL Lp>N !各根に対して
READ v(Lp),m(Lp) !1次因子x-αk、重複度m
CALL poly_divByLin(A,v(Lp), Q,R) !通分したときの係数=(分母側の多項式)/(x-αk)
FOR j=1 TO N !Lp列目に設定する
LET C(j,Lp)=Q(j-1)
NEXT j
FOR i=1 TO m(Lp)-1 !重複根なら
MAT AA=Q
CALL poly_divByLin(AA,v(Lp), Q,R) !通分したときの係数=(分母側の多項式)/(x-αk)^m
FOR j=1 TO N !Lp+i列目に設定する
LET C(j,Lp+i)=Q(j-1)
NEXT j
NEXT i
LET Lp=Lp+m(Lp) !次へ
LOOP
!!!MAT PRINT C; !debug
DIM Ci(N,N) !恒等式を解く
MAT Ci=INV(C)
MAT k=Ci*B
LET Lp=1 !結果を表示する
DO UNTIL Lp>N
FOR i=0 TO m(Lp)-1
CALL PrintOut(k(Lp+i),v(Lp),i+1)
NEXT i
LET Lp=Lp+m(Lp) !次へ
LOOP
SUB PrintOut(c,v,k) !分数を表示する
PRINT c; !分子側=C
IF v>0 THEN !分母側=x-α
PRINT "/ ( x -";v;")";
ELSEIF v<0 THEN
PRINT "/ ( x +";ABS(v);")";
ELSE
PRINT "/ x ";
END IF
IF k>1 THEN PRINT " ^";k ELSE PRINT !べき乗
END SUB
END
!補助ルーチン
!変数xの多項式 Σ[k=0,n]a(k)*x^k=a(n)*x^n+a(n-1)*x^(n-1)+ … +a(1)*x+a(0)
!演算関連
EXTERNAL FUNCTION poly_degree(A()) !次数を得る
FOR i=UBOUND(A) TO 1 STEP -1
IF A(i)<>0 THEN EXIT FOR !係数が0でない最初の位置
NEXT i
LET poly_degree=i
END FUNCTION
EXTERNAL SUB poly_divByLin(A(),v, Q(),R) !多項式a(x)をx-αで割ったときの商q(x)と余りRを求める
MAT Q=ZER
LET aa=poly_degree(A)
IF aa>0 THEN !1次式以上なら
LET qq=aa-1 !次数
LET Q(qq)=A(aa) !商 ※組立除法
FOR i=qq TO 1 STEP -1
LET Q(i-1)=A(i)+Q(i)*v
NEXT i
LET R=A(0)+Q(0)*v !余り
ELSE
LET Q(0)=0 !商
LET R=A(0) !余り
END IF
END SUB
!●記数法の計算
LET N=5 !桁数
DATA 1,1,0,1,0,1 !2進法 110101
DIM A2(0 TO N),Q2(0 TO N)
FOR i=N TO 0 STEP -1
READ A2(i)
NEXT i
CALL poly_divByLin(A2,2, Q2,R) !p(x)/(x-2)
PRINT R !10進法
!●多項式のテイラー展開
LET N=4 !次数
DATA 1,-2,-20,23,13 !x^4-2*x^3-20*x^2+23*x+13
DATA 5 !x=a
DIM A(0 TO N) !係数
FOR i=N TO 0 STEP -1
READ A(i)
NEXT i
READ v
DIM Q(0 TO N),AA(0 TO N) !作業用
MAT AA=A
FOR i=0 TO N-1 !Σf[k](a)/k!*(x-a)^k
CALL poly_divByLin(AA,v, Q,R) !k階微分係数 ※<----------
PRINT R;" * ( x -";v;") ^";i
MAT AA=Q !次へ
NEXT i
PRINT Q(0);" * ( x -";v;") ^";N
!●代数方程式の根をニュートン法で求める(関数値、微分係数)
LET cEps=1e-10 !精度 ※要調整
LET N=3 !次数
DATA 1,-2,0,-9 !x^3-2*x^2-9=(x-3)*(x^2+x+3)
LET Xk=2 !近似根
DIM A3(0 TO N),Q3(0 TO N),QQ3(0 TO N)
FOR i=N TO 0 STEP -1
READ A3(i)
NEXT i
LET iter=200 !反復回数
FOR k=1 TO iter
CALL poly_divByLin(A3,Xk, Q3,f) !関数値※<----------
CALL poly_divByLin(Q3,Xk, QQ3,df) !微分係数 ※<----------
LET WXk=Xk-f/df !Xk+1=Xk-f(Xk)/f'(Xk)
IF ABS(WXk-Xk)<=ABS(Xk)*cEps THEN EXIT FOR !収束すれば終了
LET Xk=WXk !次へ
NEXT k
IF k>iter THEN
PRINT iter;"回では収束しません。"
STOP
END IF
PRINT USING "## ##.###############": k,Xk
END
!補助ルーチン
!変数xの多項式 Σ[k=0,n]a(k)*x^k=a(n)*x^n+a(n-1)*x^(n-1)+ … +a(1)*x+a(0)
!演算関連
EXTERNAL FUNCTION poly_degree(A()) !次数を得る
FOR i=UBOUND(A) TO 1 STEP -1
IF A(i)<>0 THEN EXIT FOR !係数が0でない最初の位置
NEXT i
LET poly_degree=i
END FUNCTION
EXTERNAL SUB poly_divByLin(A(),v, Q(),R) !多項式a(x)をx-αで割ったときの商q(x)と余りrを求める
MAT Q=ZER
LET s=0
FOR i=poly_degree(A) TO 0 STEP -1 !ホーナーの方法
LET Q(i)=s !※「係数にxを掛けて次の係数を加える」が組立除法になる
LET s=s*v+A(i) !(…(((An*X+An-1)*X+An-2)*X+An-3)*X+…+A1)*X+A0
NEXT i
LET R=s
END SUB
SUB SetWindowPos( handle,C2, x0,y0,xw,yw, nFLG ) ! nFLG: 0=x0y0xwyw 1=x0y0 2=xwyw
ASSIGN "user32.dll","SetWindowPos"
END SUB
!----------------------------------------------------------
LET SU=999 ! サンプルのデーター数
DIM NO_(SU), VA$(SU) ! サンプル番号、ソートするサンプルの値
DIM stb(SU) ! 同値データー順番を、安定化する拡張配列
!
LET u_$=REPEAT$("#",LEN(STR$(SU)))
LET u0$=REPEAT$("%",LEN(STR$(SU)))
SUB PRNdata(w$)
MAT PRINT USING " / No: "& REPEAT$(u_$& " ",SU): NO_
MAT PRINT USING w$& " 値: "& REPEAT$(u_$& " ",SU): VA$
END SUB
SUB Ready
!--- サンプルの作成
RANDOMIZE 19650218 !デフォールトRND の繰返し再生
FOR i=1 TO SU
LET NO_(i)=i ! サンプル番号、固有のIDだが、乱れの識別のため登録順と同じにする。
LET VA$(i)=USING$(u0$,SU*RND) ! ソートする評価値
NEXT i
!---
FOR i=1 TO SU
LET stb(i)=i ! 同値 の登録順の安定用番号( サンプルの登録順番号 )
NEXT i
CALL PRNdata("元の順\")
LET t0=TIME
END SUB
SUB Result(w$)
!--- 結果のプリント
LET t1=TIME-t0
IF t1< 0 THEN LET t1=t1+86400
CALL PRNdata("ソート\")
FOR i=2 TO SU
IF VA$(i-1)>VA$(i) THEN EXIT FOR
NEXT i
IF SU< i THEN PRINT w$& ": ソート時間:";t1;"sec." ELSE PRINT w$& ": Error!"
PRINT
END SUB
!------
! 順序を安定化した、クイック・ソート
SUB Qsort(L,R)
local i,j
LET i=L
LET j=R
LET v$=VA$((L+R)/2)
LET ss=stb((L+R)/2)
DO
DO WHILE VA$(i)< v$ OR (VA$(i)=v$ AND stb(i)< ss)
LET i=i+1
LOOP
DO WHILE v$< VA$(j) OR (VA$(j)=v$ AND ss< stb(j))
LET j=j-1
LOOP
IF j< i THEN EXIT DO
SWAP NO_(i),NO_(j)
SWAP VA$(i),VA$(j)
SWAP stb(i),stb(j)
LET i=i+1
LET j=j-1
LOOP UNTIL j< i
IF L< j THEN CALL Qsort(L,j)
IF i< R THEN CALL Qsort(i,R)
END SUB
!------
! 通常のクイック・ソート(比較用)
SUB Qsort00(L,R)
local i,j
LET i=L
LET j=R
LET v$=VA$((L+R)/2)
DO
DO WHILE VA$(i)< v$
LET i=i+1
LOOP
DO WHILE v$< VA$(j)
LET j=j-1
LOOP
IF j< i THEN EXIT DO ! 等号付 j<=i は、暴走。
SWAP NO_(i),NO_(j)
SWAP VA$(i),VA$(j)
LET i=i+1
LET j=j-1
LOOP UNTIL j< i ! 等号付 j<=i は、低速。
IF L< j THEN CALL Qsort00(L,j)
IF i< R THEN CALL Qsort00(i,R)
END SUB
!行列関連
FUNCTION tr(A(,)) !行列Aのトレース
LET t=0
FOR i=1 TO N
LET t=t+A(i,i)
NEXT i
LET tr=t
END FUNCTION
!多項式関連
SUB mono_disp(ak,k) !単項式を表示する Ak*X^k
IF k<>0 THEN !x^nで
IF ak=1 THEN !係数が1なら
ELSEIF ak=-1 THEN !係数が−1なら
PRINT "-";
ELSE
PRINT STR$(ak);"*";
END IF
END IF
IF k=0 THEN !次数が0なら
PRINT STR$(ak);
ELSEIF k=1 THEN !次数が1なら
PRINT "s";
ELSE
PRINT "s^";STR$(k);
END IF
END SUB
!-------------------- ここまでがサブルーチン
!系 u(入力)→ [ x'=A*x+b*u、y=c*x ] →y(出力)
!---------- ↓↓↓↓↓ ----------
LET N=2 !状態変数の数
DIM A(N,N),b(N,1),c(1,N)
LET R1=30e3 !30k[Ω]
LET R2=18e3 !18k[Ω]
LET C1=0.01e-6 !0.01μ[F]
LET C2=0.0047e-6 !0.0047μ[F]
LET K=1 !ボルテージ・フォロワより、アンプの増幅率は1
LET A(1,1)=-(R1+R2)/(R1*R2*C1)
LET A(1,2)=-((K-1)*(R1+R2)+R2)/(R1*R2*C1)
LET A(2,1)=1/(R2*C2)
LET A(2,2)=(K-1)/(R2*C2)
LET b(1,1)=1/(R1*C1)
LET b(2,1)=0
LET c(1,1)=0
LET c(1,2)=K
!---------- ↑↑↑↑↑ ----------
!Frame法、Leverrir-Faddeev法
! adj(s*I-A)=s^(n-1)*I+s^(n-2)*β1+ … +s*βn-2+βn-1
! det(s*I-A)=s^n+α1*s^(n-1)+ … + αn-1*s+αn
!のとき
! β0=I、k=1〜nについて
! Xk=A*βk-1
! αk=-trace(Xk)/k
! βk=Xk+αk*I
!の逐次計算でαk、βkが求まる。
DIM p1(N) !分子側の多項式 c(1)*X^(N-1)+c(2)*X^(N-2)+ … +c(N-1)*X+c(N) の係数
DIM p2(N) !分母側の多項式 X^N+c(1)*X^(N-1)+c(2)*X^(N-2)+ … +c(N-1)*X+c(N) の係数
DIM X(N,N),sE(N,N),T1(1,N),T2(1,1) !作業用
MAT X=IDN !adj(s*I-A)
FOR k=1 TO N
MAT PRINT X; !debug
MAT T1=c*X !c*adj(s*I-A)*b ※定数*多項式*定数
MAT T2=T1*b
LET p1(k)=T2(1,1)
MAT X=A*X
LET p2(k)=-tr(X)/k !det(s*I-A)
MAT sE=(p2(k))*IDN
MAT X=X+sE
NEXT k
!※既約分数でない
!!!MAT PRINT p1; !debug
PRINT "分子= ";
FOR i=1 TO N !分子側の多項式を表示する
LET w=p1(i)
IF w>0 THEN PRINT "+";
IF w<>0 THEN CALL mono_disp(w,N-i)
NEXT i
PRINT
!!!MAT PRINT p2; !debug
PRINT "分母= ";
CALL mono_disp(1,N) !分母側の多項式を表示する
FOR i=1 TO N
LET w=p2(i)
IF w>0 THEN PRINT "+";
IF w<>0 THEN CALL mono_disp(w,N-i)
NEXT i
END
! 観賞グラフ
! 輝く マンデルブロー( 添付サンプル Complex\mandelbm.bas の着色改変)
!
OPTION ARITHMETIC COMPLEX
SET POINT STYLE 1
!
FOR n=0 TO 50
SET COLOR MIX( n) 0
,0 ,n/51 !BLACK =< < BLUE
SET COLOR MIX( 51+n) 0 ,n/51 ,1 !BLUE =< < CYAN
SET COLOR MIX(102+n) 0 ,1 ,1-n/51 !CYAN =< < GREEN
SET COLOR MIX(153+n) n/51,1 ,0 !GREEN =< < YELLOW
SET COLOR MIX(204+n) 1 ,1-n/51,0 !YELLOW =< < RED
NEXT n
!SET COLOR MIX(255) 1,0,0 !=RED
SET COLOR MIX(255) 0.549,0.549,0.561 !=GRAY =default
!
LET XL=-2
LET XR=.8
LET w1=XR-XL
LET w2=w1/2
!
SET WINDOW XL, XR,-w2,w2
ASK PIXEL SIZE(XL,-w2; XR,w2) px,py
!
! マンデルブローのμ-map
! f(z)=z^2+μの反復が有界となる複素数μの集合
! 発散の判定に至るまでの繰り返し回数で色分け。
!
FOR x=XL TO XR STEP w1/(px-1)
FOR y=0 TO w2 STEP w1/(py-1)
LET z=0
FOR n=1 TO 255
LET z=z^2+COMPLEX(x,y)
IF 2< ABS(z) THEN
IF
n< 64 THEN SET POINT COLOR n*4 ELSE SET POINT COLOR 255
PLOT POINTS :x,y
PLOT POINTS :x,-y
EXIT FOR
END IF
NEXT n
NEXT y
NEXT x
!--------------
pause !一時停止
SET COLOR MIX(0) 1,1,1
CLEAR
FOR x=XL TO XR STEP w1/(px-1)
FOR y=-w2-w1/(py-1)/2 TO w2 STEP w1/(py-1) !故意に(x,0)を描点の間に挟む。
LET z=0
FOR n=1 TO 255
LET z=z^2+COMPLEX(x,y)
IF 2< ABS(z) THEN
IF
n< 64 THEN SET POINT COLOR n*4 ELSE SET POINT COLOR 255
PLOT POINTS :x,y !上下の対象プロットをしない。
EXIT FOR
END IF
NEXT n
NEXT y
NEXT x
!不等式f(x,y)>0の領域がつくる模様
!関数の定義 f(x,y)=0
LET n=0.25
DEF g(x,y)=COS(PI*y)-n/COS(PI*x) !n=[-1,1]
!LET n=0.2
!DEF g(x,y)=x*y/n-(x^2+y^2)/(COS(2*PI*x)+COS(2*PI*y)) !n=[0.1,1]
!LET n=0.5
!DEF g(x,y)=COS(2*PI*y)-COS(2*PI*(COS(2*n*PI*x)+COS(2*n*PI*y))) !n=[0.1,2]
!LET n=3
!DEF g(x,y)=COS(PI*x*y/n)-(COS(2*PI*x)+COS(2*PI*y)) !n=[0.1,5]
!LET n=0.2
!DEF g(x,y)=n*COS(PI*x*y)-(SIN(2*PI*x)+SIN(2*PI*y)) !n=[-0.5,0.5]
!LET n=25
!DEF g(x,y)=COS(PI*x*y)-COS(n*x*y/(x^2+y^2)) !n=[1,100]
!LET n=25
!DEF g(x,y)=COS(PI*x*y)-x*y*COS(n*x*y/(x^2+y^2)) !n=[1,100]
LET a=-5 !x=[a,b] ※xy座標の表示領域
LET b=5
LET c=a !y=[c,d]
LET d=b
SET WINDOW a,b,c,d !表示領域を設定する
DRAW grid(1,1) !座標を描く
ASK PIXEL SIZE (a,c; b,d) w,h !画像の縦横の大きさ(ドット単位)を調べる
!条件を満たす領域を描く
SET POINT STYLE 1 !ドット形式
SET POINT COLOR 2
FOR j=1 TO h !画面全体を走査する
LET y=WORLDY(j) !ドットをxy座標に変換する
FOR i=1 TO w
LET x=WORLDX(i)
WHEN EXCEPTION IN
LET z=g(x,y) !関数値を計算する
IF z>0 THEN !正の部分を切り取る
PLOT POINTS: x,y
END IF
USE !0割りなどの例外処理
END WHEN
NEXT i
NEXT j
END
> 組立除法の(意外な)使い道
>
> EXTERNAL SUB poly_divByLin(A(),v, Q(),R) !多項式a(x)をx-αで割ったときの商q(x)と余りrを求める
> MAT Q=ZER
> LET s=0
> FOR i=poly_degree(A) TO 0 STEP -1 !ホーナーの方法
> LET Q(i)=s !※「係数にxを掛けて次の係数を加える」が組立除法になる
> LET s=s*v+A(i) !(…(((An*X+An-1)*X+An-2)*X+An-3)*X+…+A1)*X+A0
> NEXT i
> LET R=s
> END SUB
!●接線の方程式
!整関数y=f(x)は、組立除法で、y=Q(x)*(x-a)^2+m*(x-a)+nに変形できる。
!y=f(x)上の点P(a,f(a))における接線は、y=m*(x-a)+nになる。
LET N=3 !次数
DATA 1,0,0,0 !y=f(x)=x^3
LET a=1 !点P
DIM A2(0 TO N)
FOR i=N TO 0 STEP -1
READ A2(i)
NEXT i
CALL FxdFx(N,A2,a, f,df) !関数値と微分係数 ※<----------
PRINT df;"* (x + "; -a;") +";f !y=f'(a)*(x-a)+f(a)
!●代数方程式の根をニュートン法で求める(関数値、微分係数)
LET cEps=1e-10 !精度 ※要調整
!LET N=3 !次数
!DATA 1,-2,0,-9 !x^3-2*x^2-9=(x-3)*(x^2+x+3)
LET N=4
DATA 1,-4,-1,10,6 !(x+1)(x-3)(x^2-2*x-2)
LET Xk=4 !近似根
DIM A3(0 TO N)
FOR i=N TO 0 STEP -1
READ A3(i)
NEXT i
LET iter=200 !反復回数
FOR k=1 TO iter
CALL FxdFx(N,A3,Xk, f,df) !関数値と微分係数 ※<----------
LET WXk=Xk-f/df !Xk+1=Xk-f(Xk)/f'(Xk)
IF ABS(WXk-Xk)<=ABS(Xk)*cEps THEN EXIT FOR !収束すれば終了
LET Xk=WXk !次へ
NEXT k
IF k>iter THEN
PRINT iter;"回では収束しません。"
STOP
END IF
PRINT USING "## ##.###############": k,Xk
END
!補助ルーチン
!変数xの多項式 Σ[k=0,n]a(k)*x^k=a(n)*x^n+a(n-1)*x^(n-1)+ … +a(1)*x+a(0)
!演算関連
EXTERNAL SUB FxdFx(n,a(),x0, f,df) !関数値f(x0)と微分係数f'(x0)を求める ※n≧1
LET f=a(n)
LET df=f
FOR j=n-1 TO 1 STEP -1 !ホーナー法(組立除法)
LET f=f*x0+a(j)
LET df=df*x0+f
NEXT j
LET f=f*x0+a(0)
END SUB
BVALとBSTR$はJIS Full BASICでは実時間機能単位で定義されています。
実時間機能を実装しようとすると面倒が多々出てくるので当面その予定はありません。
ですが,2進数,16進数の表現はできないと不便なのでJIS互換となるようにその機能を用意しています。
Full BASICのBVAL(s$,r),BSTR$(n,r)はrの部分を数値式で指定できますが,十進BASICでは定数のみです。
8進に対応するのはさほど難しくないのですが,現在のPC環境でその必要性を感じることがないので省いています。
SUB div1time(i,j)
!---------- 以上の分割を1回行なうブログラム。i=L,j=R で開始。
LET v$=VA$((i+j)/2)
DO
DO WHILE VA$(i)< v$
LET i=i+1
LOOP
DO WHILE v$< VA$(j)
LET j=j-1
LOOP
IF j< i THEN EXIT DO ! 等号付 j<=i は、不良。連続の再帰で暴走する。
SWAP VA$(i),VA$(j)
LET i=i+1
LET j=j-1
LOOP UNTIL j< i ! 等号付 j<=i は、不適。連続の再帰で低速。
!----------
END SUB
!===================
SUB QuickSort(L,R) ! 上を、連続に行なうブログラム。
local i,j
LET i=L
LET j=R
!----------
! 上のプログラム("---"の内側)を、ココに置いて、
! 再帰的に、繰返し使用。
!----------
CALL div1time(i,j) !これでも良い。…再帰文の分離は、local 変数に用心!
!----------
IF L< j THEN CALL QuickSort(L,j) !データー数1個以下( L>=j) になるまで。
IF i< R THEN CALL QuickSort(i,R) !データー数1個以下( i>=R) になるまで。
END SUB
!========================== 上記の動作の、図解アニメーション ============
!LET samp$="079427856083621"
LET samp$="0794278069836215794278560836215806083"
LET L=1
LET R=LEN(samp$)
FOR k=L TO R
LET VA$(k)=samp$(k:k)
NEXT k
!
SET TEXT background "Opaque"
SET TEXT font "MS ゴシック",11
SET WINDOW -1,40, 30,0
SET LINE width 2
PLOT TEXT,AT 1,1.5:"** クイック・ソートの手順 **"
LET s=26
PLOT TEXT,AT 1,s :"下線の付いた文字は、L~ R 中央位置で選ばれた「基準値」"
PLOT TEXT,AT 1,s+1 :"その「基準値」で、分割された下の段の色分、"
SET COLOR MIX(0) 0,1,1
PLOT TEXT,AT 1,s+2 :"青は「基準値」以下"
SET COLOR MIX(0) 1,1,0
PLOT TEXT,AT 13,s+2 :"黄は「基準値」以上"
SET COLOR MIX(0) 1,1,1
PLOT TEXT,AT 25,s+2 :"(無色:分割不要、確定)"
PLOT TEXT,AT 1,s+3 :"描画の順序は、再帰文としての、実行順序そのまま。"
LET s=3
!
CALL plotVA(L,R,s,L,R)
CALL GraphQS(L,R)
CALL plotVA(L,R,m+1,L,R)
SUB GraphQS(L,R) ! 分割繰返しの構造を、グラフィックに表示。
local i,j
LET i=L
LET j=R
LET s=s+1
SET COLOR MIX(0) 1,1,1
PLOT TEXT,AT L,s :"L"
PLOT TEXT,AT R,s :"R"
LET s=s+1
!----------
CALL div1time(i,j) !← 冒頭の(分割を1回行なう・・)文を、実際に使用。
CALL plotVA(L,R,s,i,j)
IF m< s THEN LET m=s
WAIT DELAY .1 ! 描画の速さの調整。
!----------
IF L< j THEN CALL GraphQS(L,j)
IF i< R THEN CALL GraphQS(i,R)
LET s=s-2
END SUB
SUB plotVA(L,R,y,i,j)
FOR x=L TO R
IF L=i AND R=j THEN
SET COLOR MIX(0) .8,.8,.8
!SET COLOR MIX(0) 1,1,1
ELSEIF x<=j THEN
SET COLOR MIX(0) 0,1,1
ELSEIF i<=x THEN
SET COLOR MIX(0) 1,1,0
ELSE
SET COLOR MIX(0) 1,1,1
END IF
PLOT TEXT,AT x,y :VA$(x)
IF L<>j AND ROUND((L+j)/2)=x OR i<>R AND ROUND((i+R)/2)=x THEN
PLOT LINES:x+.2,y;x+.6,y
END IF
NEXT x
END SUB
LET E=10
LET R1=1000
LET i1=E/R1/2
LET i2=0
LET L1=50 !0.1 小さいと、オーバーフロー?
LET L2=2 !0.1 小さいと、オーバーフロー?
LET R2=10
LET M=SQR(L1*L2)
LET w9=2*PI*1 !50 小さいと、描画ピッチ演算ピッチ共に無理
!
LET dt=0.05 !sec. 演算ピッチ。描画ピッチが遅れない程度に。
SUB RungeKutta4_1(t, i1)
LET k1=f1(t, i1)
LET k2=f1(t+dt/2, i1+k1*dt/2)
LET k3=f1(t+dt/2, i1+k2*dt/2)
LET k4=f1(t+dt, i1+k3*dt )
LET i1=i1+(k1+2*k2+2*k3+k4)*dt/6
LET f1_=f1(t, i1)
END SUB
SUB RungeKutta4_2(t, i2)
LET k1=f2(t, i2)
LET k2=f2(t+dt/2, i2+k1*dt/2)
LET k3=f2(t+dt/2, i2+k2*dt/2)
LET k4=f2(t+dt, i2+k3*dt )
LET i2=i2+(k1+2*k2+2*k3+k4)*dt/6
LET f2_=f2(t, i2)
END SUB
!----run
LET t=0
LET w=.5 !13
SET WINDOW -w,w,-w,w
SET LINE width 3
SET COLOR MIX(15) .5,.5,.5
SET TEXT background "OPAQUE"
LET t0=TIME
DO
LET t1=TIME
IF dt=< ABS(t1-t0) THEN
SET DRAW mode hidden
CLEAR
DRAW grid(5,5)
PLOT TEXT,AT w*0.25,w*0.9:"マウス 右ボタンで、終了。"
PLOT TEXT,AT w*0.4,w*0.76,USING"演算ピッチ=#.### 秒":dt
PLOT TEXT,AT w*0.4,w*0.69,USING"描画ピッチ=#.### 秒":t1-t0
LET t0=t1
PRINT t;i1;i2;f1_;f2_
!---
PLOT TEXT,AT-w/2.5,i1:"i1"
PLOT TEXT,AT w/2.9,i2:"i2"
PLOT LINES :-w/3,i1;0,i1
PLOT LINES : w/3,i2;0,i2
!---
SET DRAW mode explicit
CALL RungeKutta4_1(t,i1) ! 次のi1 へ更新
CALL RungeKutta4_2(t,i2) ! 次のi2 へ更新
LET t=t+dt
END IF
WAIT DELAY 0 ! 省電力効果
MOUSE POLL mx,my,mlb,mrb
LOOP UNTIL mrb=1
LET E=10
LET R1=1000
LET L1=0.5 !0.2以下にするとオーバーフロー?
LET L2=0.1
LET R2=10
LET M=SQR(L1*L2)
LET frq=50 !信号周波数[Hz]
LET dt=0.001 !微分時間[s]
LET drawTime=0.1 ![s] !描画時間で、frq×drawTimeサイクル分だけ描画する。
LET iBairitu=500 !電流波形描画拡大倍率
LET i1_=0 ! i1の初期値
LET i2_=0 ! i2の初期値
LET Vt_=E !変圧器一次電圧Vtの初期値
LET t_=0 ! tの初期値
SUB RungeKutta4_1(t_, i1_,i1)
LET k1=f1(t_, i1_)
LET k2=f1(t_+dt/2, i1_+k1*dt/2)
LET k3=f1(t_+dt/2, i1_+k2*dt/2)
LET k4=f1(t_+dt, i1_+k3*dt )
LET i1=i1_+(k1+2*k2+2*k3+k4)*dt/6
LET f1_=f1(t_, i1)
END SUB
SUB RungeKutta4_2(t_, i2_,i2)
LET k1=f2(t_, i2_)
LET k2=f2(t_+dt/2, i2_+k1*dt/2)
LET k3=f2(t_+dt/2, i2_+k2*dt/2)
LET k4=f2(t_+dt, i2_+k3*dt )
LET i2=i2_+(k1+2*k2+2*k3+k4)*dt/6
LET f2_=f2(t_, i2)
END SUB
!----run
LET w=2*PI*frq !交流信号の角周波数[rad/s]
LET nmax=drawTime/dt !計算点数
SET WINDOW -0,drawTime,-15,15
DRAW grid
FOR n=1 TO nmax
LET t=n*dt
CALL RungeKutta4_1(t_,i1_,i1)
CALL RungeKutta4_2(t_,i2_,i2)
LET Vt=E-R1*(1+SIN(w*t))*i1
SET LINE COLOR "red" !電流i1波形描画色
PLOT LINES:t_,i1_*iBairitu;t,i1*iBairitu
SET LINE COLOR "black" !電圧波形描画色
PLOT LINES:t_,Vt_;t,Vt
PLOT LINES: t_,0;t,0 !時間軸描画
LET t_=t ! 次のt へ更新
LET i1_=i1 ! 次のi1 へ更新
LET i2_=i2 ! 次のi2 へ更新
LET Vt_=Vt ! 次のi2 へ更新
Next N
!回路図
! →i1 N:1 →i2
! ┌r───・┐ ┌────┬
! E Vt↑L1 L2↑V2 R2
! └─────┘ └・───┴
!抵抗rから変圧器までのFパラメータ(二端子対回路としてみると)
! ┌ 1 r ┐┌ N 0 ┐=┌ N r/N ┐
! └ 0 1 ┘└ 0 1/N ┘ └ 0 1/N ┘
!ただし、巻き数比N=SQR(L1/L2)とする。
!二端子対の両端の電圧、電流は
! ┌ E ┐=┌ N r/N ┐┌ V2 ┐
! └ i1 ┘ └ 0 1/N ┘└ i2 ┘
!となり、整理すると
! ┌ E ┐=┌ N*V2+r/N*i2 ┐ … ��
! └ i1 ┘ └ 1/N*i2 ┘ … ��
!二次側電圧V2=R2*i2より、i2=V2/R2 … ��
!��を�,紡綟�して、V2=(N*R2)/(r+N^2*R2)*E … ��
!これを��に代入して、i2=N/(r+N^2*R2)*E … ��
!�△紡綟�して、i1=E/(r+N^2*R2) … ��
!また、変圧器の一次側電圧Vt=E-r*i1 … �� である。
LET E=10
LET L1=0.5
LET R1=1000
DEF r=R1*(1+SIN(w*t))
LET w=2*PI*50
LET R2=10
LET L2=0.1
LET N=SQR(L1/L2)
SUB routine
LET V2=N*R2*E/(r+N^2*R2)
LET i2=N*E/(r+N^2*R2)
LET i1=E/(r+N^2*R2)
LET Vt=E-r*i1
END SUB
LET yy=12 !縦軸の範囲
LET TT=50e-3 !時間区間 [0,T]
!!!SET bitmap SIZE 600,600 !画面を大きくする
SET WINDOW -TT/8,TT,-yy,yy !表示領域
DRAW grid(TT/5,yy/6)
PLOT TEXT ,AT TT*7/8,0: "[秒]"
SET LINE COLOR 1
PLOT LINES: t,Vt; t,Vt
SET LINE COLOR 4
PLOT LINES: t,i1; t,i1
FOR t=0 TO TT STEP TT/10000
CALL routine
!!!PRINT t;i1,V2;i2
SET LINE COLOR 1
PLOT LINES: t,Vt; t,Vt
SET LINE COLOR 4
PLOT LINES: t,i1; t,i1 !※
NEXT t
PLOT LINES
END
●その2
!回路図
! →i1 →i2
! ┌r───・┐ ┌────┬
! E V1↑L1 L2↑V2 R2
! └─────┘ └・───┴
! E-r*i1=V1=L1*Δi1/Δt-M*Δi2/Δt
! M*Δi1/Δt-L2*Δi2/Δt=V2=R2*i2
!2変数i1,i2の連立1次常微分方程式で表される。
!行列で表現すると
! ┌ E-r*i1 ┐=┌ L1 -M ┐┌ Δi1/Δt ┐
! └ R2*i2 ┘ └ M -L2 ┘└ Δi2/Δt ┘
! ┌ Δi1/Δt ┐=1/(-L1*L2+M*M)┌ -L2 M ┐┌ E-r*i1 ┐
! └ Δi2/Δt ┘ └ -M L1 ┘└ R2*i2 ┘
!ところで、M=SQR(L1*L2)より、上記の変形はできない。
!したがって、M=k*SQR(L1*L2)として考える。
!精度が悪いため、計算の後半では誤差が累積されやすくなる。
!2変数の連立1次常微分方程式の解
!----- ↓↓↓↓↓ -----
LET yy=12 !縦軸の範囲
LET TT=50e-3 !時間区間 [0,T]
DEF r(t)=R1*(1+SIN(w*t))
!DEF f1(t,i1,i2)=1/(L1*L2-M*M)*(L2*(E-r(t)*i1) - M*R2*i2)
!DEF f2(t,i1,i2)=1/(L1*L2-M*M)*(-M*(E-r(t)*i1) +L1*R2*i2)
DEF f1(t,i1,i2)=1/(-L1*L2+M*M)*(-L2*(E-r(t)*i1) + M*R2*i2)
DEF f2(t,i1,i2)=1/(-L1*L2+M*M)*( -M*(E-r(t)*i1) +L1*R2*i2)
LET E=10 ![V]
LET L1=0.5 ![H]
LET R1=1000 ![Ω]
LET w=2*PI*50 ![rad/s]
LET L2=0.1 ![H]
LET R2=10 ![Ω]
LET K=0.999 !理想変圧器 K=1 ※
LET M=K*SQR(L1*L2) ![H]
!----- ↑↑↑↑↑ -----
!!!SET bitmap SIZE 600,600 !画面を大きくする
SET WINDOW -TT/8,TT,-yy,yy !表示領域
DRAW grid(TT/5,yy/6)
PLOT TEXT ,AT TT*7/8,0: "[秒]"
!●オイラー法
LET t=0 !初期値 i1(0)=0、i2(0)=0
LET i1=0
LET i2=0
SET LINE COLOR 1
PLOT LINES: t,E-r(t)*i1; t,E-r(t)*i1
SET LINE COLOR 4
PLOT LINES: t,i1; t,i1
LET h=TT/500000 !刻み幅 ※
FOR i=1 TO 500000
LET k1=h*f1(t,i1,i2)
LET k2=h*f2(t,i1,i2)
LET i1=i1+k1
LET i2=i2+k2
LET t=t+h
!!!PRINT t,i1,i2
SET LINE COLOR 1
PLOT LINES: t,E-r(t)*i1; t,E-r(t)*i1
SET LINE COLOR 4
PLOT LINES: t,i1; t,i1
NEXT i
PLOT LINES
END
LET E=10
LET R1=10000
LET ketugo=0.8 !結合係数で、1に近づけると波形が鋭利になり発振する
LET L1=0.2
LET L2=0.1
LET R2=2
LET frq=10000 !信号周波数[Hz]
LET ndiv=5000 !1サイクルの計算分割数
LET drawHz=10 ! 1画面で表示するサイクル数[Hz]
LET pass_gamen=1 !初期過渡時の描画面をパスする回数
LET iBairitu=1000 !電流波形描画拡大倍率。1000で1目盛り1[mA]になる
LET nmax=drawHz*ndiv !1画面の描画点数
LET dt=1/frq/ndiv !計算微分時間[s]
LET M=ketugo*SQR(L1*L2)
LET w=2*PI*frq !交流正弦波信号の角周波数[rad/s]
LET i1_=0 ! i1の初期値
LET i2_=0 ! i2の初期値
LET Vt_=0 !変圧器一次電圧Vtの初期値
LET t_=0 ! tの初期値
!----run
SET WINDOW -0,nmax,-2*E,2*E
DRAW grid
FOR nn=0 TO pass_gamen
FOR n=0 TO nmax
IF n=0 THEN LET xn_=0
LET t=n*dt
LET xn=n
CALL RungeKutta4_1(t_,i1_,i1)
CALL RungeKutta4_2(t_,i2_,i2)
LET Vt=E-R1*(1+SIN(w*t))*i1
IF nn=pass_gamen THEN
SET LINE COLOR "red" !電流i1波形描画色
PLOT LINES:xn_,i1_*iBairitu;xn,i1*iBairitu
!SET LINE COLOR "blue" !電流i2波形描画色
!PLOT LINES:xn_,i2_*iBairitu;xn,i2*iBairitu
SET LINE COLOR "black" !電圧波形描画色
PLOT LINES:xn_,Vt_;xn,Vt
PLOT LINES: xn_,0;xn,0 !時間軸描画
SET LINE COLOR "green" !電圧±E[V]ライン
PLOT LINES:xn_,-E;xn,-E
PLOT LINES:xn_,E;xn,E
END IF
LET t_=t ! 次のt へ更新
LET i1_=i1 ! 次のi1 へ更新
LET i2_=i2 ! 次のi2 へ更新
LET Vt_=Vt ! 次のVt へ更新
LET xn_=xn
next N
NEXT nn
SUB RungeKutta4_1(t_, i1_,i1)
LET k1=f1(t_, i1_)
LET k2=f1(t_+dt/2, i1_+k1*dt/2)
LET k3=f1(t_+dt/2, i1_+k2*dt/2)
LET k4=f1(t_+dt, i1_+k3*dt )
LET i1=i1_+(k1+2*k2+2*k3+k4)*dt/6
LET f1_=f1(t_, i1)
END SUB
SUB RungeKutta4_2(t_, i2_,i2)
LET k1=f2(t_, i2_)
LET k2=f2(t_+dt/2, i2_+k1*dt/2)
LET k3=f2(t_+dt/2, i2_+k2*dt/2)
LET k4=f2(t_+dt, i2_+k3*dt )
LET i2=i2_+(k1+2*k2+2*k3+k4)*dt/6
LET f2_=f2(t_, i2)
END SUB
END
> しまむら1243さんへのお返事です。
> > 2)電流波形は正弦波振動しません。
> i=E/Rだから、分母のRを0〜2*R(正弦波)としても、iは正弦波になりません。
>
> SET WINDOW -1,5,-1,15
> DRAW grid
>
> LET E=1
> LET R1=5
> FOR t=0 TO 5 STEP 0.001
> LET r=R1*(1+SIN(5*t))
> LET i=E/r
> PLOT LINES: t,r; t,r !正弦波
> !PLOT LINES: t,i; t,i !正弦波?
> NEXT t
>
> END
FOR bs=101 TO 1201 STEP 100
PRINT "BITMAP SIZE "&STR$(bs)&"×"&STR$(bs)
SET bitmap SIZE bs,bs
10 SET WINDOW 0,800,0,800
SET TEXT HEIGHT 30
FOR w=1 TO 3 ! w=4,5はw=3と同じ挙動
PRINT "LINE WIDTH =";w
FOR j=-32 TO -10
CALL test
NEXT j
FOR j=10 TO 32
CALL test
NEXT j
PRINT
NEXT w
PRINT
NEXT bs
SUB test
CLEAR
PLOT TEXT ,AT 300,560 : "BITMAP SIZE "&STR$(bs)&"×"&STR$(bs)
PLOT TEXT ,AT 300,480 : "w = "&STR$(w)
PLOT TEXT ,AT 300,400 : "j = "&STR$(j)
20 LET m=SGN(j)*2^ABS(j)
30 SET LINE WIDTH w
31 !SET LINE STYLE 2
40 FOR i=1 TO 400
50 PLOT LINES: 0,-m+i; 200,-m+i
60 NEXT i
LET err=0
FOR y=0 TO 800
ASK PIXEL VALUE(1,y) col
IF col=1 THEN LET err=1
NEXT y
IF err=1 THEN
PRINT j;
WAIT DELAY 0.3
END IF
END SUB
70 END
全結果
BITMAP SIZE 101×101
LINE WIDTH = 1
LINE WIDTH = 2
-32 -31 31 32
LINE WIDTH = 3
-32 -31 31 32
BITMAP SIZE 201×201
LINE WIDTH = 1
LINE WIDTH = 2
-32 -31 -30 30 31 32
LINE WIDTH = 3
-32 -31 -30 30 31 32
BITMAP SIZE 301×301
LINE WIDTH = 1
LINE WIDTH = 2
-32 -31 31 32
LINE WIDTH = 3
-32 -31 31 32
SET WINDOWで定義される座標系をGDI座標系と一致させるために
ASK PIXEL SIZE (0,1;1,0) a,b
LET a=a-1
LET b=b-1
SET WINDOW 0,a,b,0
で座標系を定義してください。
Windowsでは,左上端座標が原点(0,0)で,右下方向に座標値が増加します。
FOR bs=101 TO 1201 STEP 100
PRINT "BITMAP SIZE "&STR$(bs)&"×"&STR$(bs)
SET bitmap SIZE bs,bs
!SET bitmap SIZE 640,480
ASK PIXEL SIZE (0,1;1,0) a,b
LET a=a-1
LET b=b-1
SET WINDOW 0,a,b,0
!!!10 SET WINDOW 0,800,0,800
SET TEXT HEIGHT 30
FOR w=1 TO 3 ! w=4,5はw=3と同じ挙動
PRINT "LINE WIDTH =";w
FOR j=-32 TO -10
CALL test
NEXT j
FOR j=10 TO 32
CALL test
NEXT j
PRINT
NEXT w
PRINT
NEXT bs
SUB test
CLEAR
PLOT TEXT ,AT 300,560 : "BITMAP SIZE "&STR$(bs)&"×"&STR$(bs)
PLOT TEXT ,AT 300,480 : "w = "&STR$(w)
PLOT TEXT ,AT 300,400 : "j = "&STR$(j)
20 LET m=SGN(j)*2^ABS(j)
30 SET LINE WIDTH w
31 !!!SET LINE STYLE 2
40 FOR i=1 TO 400
50 PLOT LINES: 0,m+i; 200,m+i !左端に発生<---------- ※
!52 PLOT LINES: m+i,0; m+i,200 !上端<---------- ※
60 NEXT i
LET err=0
FOR y=0 TO 800
ASK PIXEL VALUE(0,y) col !左端<---------- ※
!ASK PIXEL VALUE(y,0) col !上端<---------- ※
IF col=1 THEN LET err=1
NEXT y
IF err=1 THEN
PRINT j;
WAIT DELAY 0.3
END IF
END SUB
70 END
Windows XPで観察される現象は,GDIに渡した座標値の上位,何ビットかを無視して処理されていることです。その範囲が明確になれば対応は可能です。
現状は,-2^31より小さければ-2^31に書き換え,2^31-1より大きければ2^31-1に書き換えています。SDKの記述が間違っているとのことなので,これを-2^26〜2^26-1の範囲に変えればいいのだろうと思います。
>> Windows Meの場合は,GDIの座標系が16ビットなので,
>> ピクセル座標系に変換した後,-2^15〜2^15-1の範囲に
>> 座標値を切り詰めた後に描画させています
これならちゃんと描画するのでは?
OPTION CHARACTER byte
LET w=320
LET h=240
SET BITMAP SIZE w,h !画面サイズ
SET WINDOW 0,w-1,0,h-1 !左下が原点。横がX、縦Y
LET hWnd=FndWnd("TPaintForm","") !ウインドウハンドルを取得する
LET Rect$=REPEAT$(" ",4*4)
LET n=ClientRect(hWnd, Rect$)
PRINT int32(Rect$,0);int32(Rect$,4);int32(Rect$,8);int32(Rect$,12)
LET n=GetWndRect(hWnd, Rect$)
PRINT int32(Rect$,0);int32(Rect$,4);int32(Rect$,8);int32(Rect$,12)
IF hWnd>0 THEN
LET hDC=GetWndDC(hWnd) !デバイスコンテキストを取得する
IF hDC>0 THEN
!LET n=SetForeWnd(hWnd)
LET n=Ellipse(hDC,20,20,100,200)
LET m=-2^16 !<-------------------- -2^15〜2^15はOK
LET n=MoveTo(hDC,0,m,0) !
LET n=LineTo(hDC,200,m) !
WAIT DELAY 2
LET n=ReleaseDC(hWnd, hDC) !デバイスコンテキストを開放する
END IF
END IF
END
!--------------------------------------------------
!
EXTERNAL FUNCTION DWORD$(n)
OPTION CHARACTER byte
LET r=MOD(n,2^8)
LET s$=CHR$(r)
LET n=(n-r)/2^8
LET r=MOD(n,2^8)
LET s$=s$ & CHR$(r)
LET n=(n-r)/2^8
LET r=MOD(n,2^8)
LET s$=s$ & CHR$(r)
LET n=(n-r)/2^8
LET r=MOD(n,2^8)
LET DWORD$=s$ & CHR$(r)
END FUNCTION
EXTERNAL FUNCTION WORD$(n)
OPTION CHARACTER byte
LET r=MOD(n,2^8)
LET s$=CHR$(r)
LET n=(n-r)/2^8
LET r=MOD(n,2^8)
LET WORD$=s$ & CHR$(r)
END FUNCTION
EXTERNAL FUNCTION int32(s$,p)
OPTION CHARACTER byte
LET n=0
FOR i=1 TO 4
LET n=n+256^(i-1)*ORD(s$(p+i:p+i))
NEXT i
IF n<2^31 THEN LET int32=n ELSE LET int32=n-2^32
END FUNCTION
EXTERNAL FUNCTION int16(s$,p)
OPTION CHARACTER byte
LET n=0
FOR i=1 TO 2
LET n=n+256^(i-1)*ORD(s$(p+i:p+i))
NEXT i
IF n<2^15 THEN LET int16=n ELSE LET int16=n-2^16
END FUNCTION
!user32.dll
EXTERNAL FUNCTION CloseWnd(hWnd)
ASSIGN "user32.dll","CloseWindow"
END FUNCTION
EXTERNAL FUNCTION CopyRect(lpDstRect$, lpSrcRect$)
ASSIGN "user32.dll","CopyRect"
END FUNCTION
EXTERNAL FUNCTION FndWnd(lpClassName$, lpWindowName$)
ASSIGN "user32.dll","FindWindowA"
END FUNCTION
EXTERNAL FUNCTION FillRect(hDC, lpRect$, hbr)
ASSIGN "user32.dll","FillRect"
END FUNCTION
EXTERNAL FUNCTION GetActWnd
ASSIGN "user32.dll","GetActiveWindow"
END FUNCTION
EXTERNAL FUNCTION ClientRect(hWnd, lpRect$)
ASSIGN "user32.dll","GetClientRect"
END FUNCTION
EXTERNAL FUNCTION GetForeWnd
ASSIGN "user32.dll","GetForegroundWindow"
END FUNCTION
EXTERNAL FUNCTION GetWndDC(hWnd)
ASSIGN "user32.dll","GetWindowDC"
END FUNCTION
EXTERNAL FUNCTION GetWndRect(hWnd, lpRect$)
ASSIGN "user32.dll","GetWindowRect"
END FUNCTION
EXTERNAL FUNCTION IsWndVisible(hWnd)
ASSIGN "user32.dll","IsWindowVisible"
END FUNCTION
EXTERNAL FUNCTION MoveWnd(hWnd, x, y, cx, cy)
ASSIGN "user32.dll","MoveWindow"
END FUNCTION
EXTERNAL FUNCTION OffsetRect(lpRect$, dx, dy)
ASSIGN "user32.dll","OffsetRect"
END FUNCTION
EXTERNAL FUNCTION ReleaseDC(hWnd, hDC)
ASSIGN "user32.dll","ReleaseDC"
END FUNCTION
EXTERNAL FUNCTION SetActWnd(hWnd)
ASSIGN "user32.dll","SetActiveWindow"
END FUNCTION
EXTERNAL FUNCTION SetForeWnd(hWnd)
ASSIGN "user32.dll","SetForegroundWindow"
END FUNCTION
EXTERNAL FUNCTION SetRect(lpRect$, xLeftRect, yTopRect, xRightRect, yBottomRect)
ASSIGN "user32.dll","SetRect"
END FUNCTION
EXTERNAL FUNCTION SetWndPos(hWnd, hWndInsertAfter, x, y, cx, cy, uFlag)
ASSIGN "user32.dll","SetWindowPos"
END FUNCTION
EXTERNAL FUNCTION SetWndText(hWnd, lpString$)
ASSIGN "user32.dll","SetWindowTextA"
END FUNCTION
EXTERNAL FUNCTION ShowWnd(hWnd, nCmdShow)
ASSIGN "user32.dll","ShowWindow"
END FUNCTION
!gdi32.dll
EXTERNAL FUNCTION SolidBrush(crColor)
ASSIGN "gdi32.dll","CreateSolidBrush"
END FUNCTION
EXTERNAL FUNCTION Ellipse(hDC, nLeftRect, nTopRect, nRightRect, nBottomRect)
ASSIGN "gdi32.dll","Ellipse"
END FUNCTION
EXTERNAL FUNCTION LineTo(hDC, x, y)
ASSIGN "gdi32.dll","LineTo"
END FUNCTION
EXTERNAL FUNCTION MoveTo(hDC, x, y, lpPoint)
ASSIGN "gdi32.dll","MoveToEx"
END FUNCTION
EXTERNAL FUNCTION Rectangle(hDC, nLeftRect, nTopRect, nRightRect, nBottomRect)
ASSIGN "gdi32.dll","Rectangle"
END FUNCTION
OPTION ARITHMETIC NATIVE !CPUパワー
SET COLOR MODE "NATIVE"
GLOAD "c:\BASICw32\SAMPLE\ZENKOUJI.JPG" !画像を読み込む
ASK PIXEL SIZE (0,0; 1,1) w,h !画像の縦横の大きさ(ピクセル単位)を調べる
DIM p(w,h),q(w,h) !画像の大きさに対応する配列要素を用意する
ASK PIXEL ARRAY (0,1) p !画像の各点の色情報を配列に格納する
PRINT "画像の大きさ 縦:";h;" 横:";w
!SET BITMAP SIZE w,h !ウィンドウの大きさを画像に合わせる
LET R=30 !めくりの半径 ※
LET Dx=20 !めくりの量 ※
LET th=RAD(30) !めくりの方向 ※
DIM M1(3,3),M2(3,3),M4(3,3),M5(3,3),M7(3,3),M8(3,3)
MAT M1=IDN !画像の中央を原点へ
LET M1(1,3)=-w/2
LET M1(2,3)=-h/2
MAT M2=IDN !めくり方向をX軸に一致させ、半径を1とする
LET M2(1,1)=COS(th)/R
LET M2(1,2)=SIN(th)/R
LET M2(2,1)=-SIN(th)/R
LET M2(2,2)=COS(th)/R
MAT M4=IDN !めくりの中心を原点へ
LET M4(1,3)=-Dx/R
MAT M5=IDN !INV(M4)
LET M5(1,3)=Dx/R
MAT M7=IDN !INV(M2)
LET M7(1,1)=COS(th)*R
LET M7(1,2)=-SIN(th)*R
LET M7(2,1)=SIN(th)*R
LET M7(2,2)=COS(th)*R
MAT M8=IDN !INV(M1)
LET M8(1,3)=w/2
LET M8(2,3)=h/2
MAT q=ZER !黒色
!座標変換 f:(x,y)→(xx,yy)の逆変換を考える
!下側の部分
DIM t(3)
FOR yy=1 TO h !変換後の画素位置で走査する
FOR xx=1 TO w
LET t(1)=xx !非線形変換前の線形変換
LET t(2)=yy
LET t(3)=1
MAT t=M1*t
MAT t=M2*t
MAT t=M4*t
!非線形変換
!横から見た図(効果のかかる方向をX軸方向にとる)
!Z軸
!↑
!・→ X軸
! 視線
! ↓
! x'=1
! ──・ 上側
! \ ↑
! めくりの中心 → * ・x'=0 --------
! / ↓
! 画素面 ─────・ 下側
! x'=-1
!
!・下側と上側の順に2回の描画で陰面消去を行う
LET op=0 !計算誤差を避けるため元の値を使う
SELECT CASE t(1) !x'=R*Sin(θz)
CASE IS >=1
LET op=-1 !NOP
CASE IS >=0
LET t(1)=ASIN(ABS(t(1))) !0≦R*ArcSin(x'/R)≦R*PI/2
LET op=1 !変換された座標を使う
CASE ELSE !x'
END SELECT
MAT t=M5*t !非線形変換後の線形変換
MAT t=M7*t
MAT t=M8*t
!PRINT xx;yy !debug
!MAT PRINT t;
LET x=INT(t(1)) !元の画素での位置
LET y=INT(t(2))
SELECT CASE op !元の画素を読み込んで書き込む
CASE 0
LET q(xx,yy)=p(xx,yy)
CASE 1
IF x<1 OR x>w OR y<1 OR y>h THEN !範囲内なら
ELSE
LET q(xx,yy)=p(x,y)
END IF
CASE ELSE
END SELECT
NEXT xx
NEXT yy
!MAT PLOT CELLS, IN 0,1; 1,0 :q !画像を表示する debug
!STOP
!上側の部分(めくり上がって裏返る部分)
FOR yy=1 TO h !変換後の画素位置で走査する
FOR xx=1 TO w
LET t(1)=xx !非線形変換前の線形変換
LET t(2)=yy
LET t(3)=1
MAT t=M1*t
MAT t=M2*t
MAT t=M4*t
!非線形変換
!!!●巻き込まない場合は、こちら
LET op=0 !計算誤差を避けるため元の値を使う
SELECT CASE t(1)
CASE IS >=1
LET op=-1 !NOP
CASE IS >=0
LET t(1)=PI-ASIN(ABS(t(1))) !R*PI/2≦R*PI-R*ArcSin(x'/R)≦R*PI
LET op=1
CASE ELSE
LET t(1)=PI-t(1) !R*PI-x'
LET op=1
END SELECT
!!!●巻き込む場合は、こちら
!!!LET op=0 !計算誤差を避けるため元の値を使う
!!!SELECT CASE t(1)
!!!CASE IS >=1
!!! LET op=-1 !NOP
!!!CASE IS >=0
!!! LET t(1)=PI-ASIN(ABS(t(1)))
!!! LET op=1
!!!CASE IS >=-1
!!! LET t(1)=PI+ASIN(ABS(t(1)))
!!! LET op=1
!!!CASE ELSE
!!! LET op=-1 !NOP
!!!END SELECT
MAT t=M5*t !非線形変換後の線形変換
MAT t=M7*t
MAT t=M8*t
!PRINT xx;yy !debug
!MAT PRINT t;
LET x=INT(t(1)) !元の画素での位置
LET y=INT(t(2))
SELECT CASE op !元の画素を読み込んで書き込む
CASE 0
LET q(xx,yy)=p(xx,yy)
CASE 1
IF x<1 OR x>w OR y<1 OR y>h THEN !範囲内なら
ELSE
LET q(xx,yy)=p(x,y)
END IF
CASE ELSE
END SELECT
NEXT xx
NEXT yy
MAT PLOT CELLS, IN 0,1; 1,0 :q !画像を表示する
END
OPTION ARITHMETIC NATIVE !CPUパワー
SET COLOR MODE "NATIVE"
GLOAD "c:\BASICw32\SAMPLE\ZENKOUJI.JPG" !画像を読み込む
ASK PIXEL SIZE (0,0; 1,1) w,h !画像の縦横の大きさ(ピクセル単位)を調べる
DIM p(w,h),q(w,h) !画像の大きさに対応する配列要素を用意する
ASK PIXEL ARRAY (0,1) p !画像の各点の色情報を配列に格納する
PRINT "画像の大きさ 縦:";h;" 横:";w
!SET BITMAP SIZE w,h !ウィンドウの大きさを画像に合わせる
LET Rx=100 !球の半径
LET Ry=100
LET Sx=150 !球の中心
LET Sy=150
LET Tx=w/2+50 !貼付け位置
LET Ty=h/2
DIM M1(3,3),M2(3,3),M3(3,3),M6(3,3),M7(3,3),M8(3,3)
MAT M1=IDN !中心の移動
LET M1(1,3)=-Sx
LET M1(2,3)=-Sy
MAT M2=IDN !比率の変換
LET M2(1,1)=1/Rx
LET M2(2,2)=1/Ry
MAT M7=IDN !INV(M2)
LET M7(1,1)=Rx
LET M7(2,2)=Ry
MAT M8=IDN !貼付け画像の移動
LET M8(1,3)=Tx
LET M8(2,3)=Ty
MAT q=ZER !黒色
!座標変換 f:(x,y)→(xx,yy)の逆変換を考える
DIM t(3)
FOR yy=1 TO h !変換後の画素位置で走査する
FOR xx=1 TO w
LET t(1)=xx !非線形変換前の線形変換
LET t(2)=yy
LET t(3)=1
MAT t=M1*t
MAT t=M2*t
LET tt=SQR(t(1)*t(1)+t(2)*t(2)) !(x,y)に応じて回転する
IF tt=0 THEN
LET co=0
LET si=0
ELSE
LET co=t(1)/tt
LET si=t(2)/tt
END IF
MAT M3=IDN
LET M3(1,1)=co !X軸上への写像
LET M3(1,2)=si
LET M3(2,1)=-si
LET M3(2,2)=co
MAT t=M3*t
!非線形変換
IF t(1)>=0 AND t(1)<1 THEN !球の内
LET t(1)=ASIN(t(1)) !凸
!LET t(1)=ATN(t(1))*1.5 !凹
LET op=1 !変換された座標を使う
ELSE !球の外
LET op=0 !計算誤差を避けるため元の値を使う
END IF
SELECT CASE op !元の画素を読み込んで書き込む
CASE 0
LET q(xx,yy)=p(xx,yy)
CASE 1
MAT M6=IDN !INV(M3) !非線形変換後の線形変換
LET M6(1,1)=co
LET M6(1,2)=-si
LET M6(2,1)=si
LET M6(2,2)=co
MAT t=M6*t
MAT t=M7*t
MAT t=M8*t
!PRINT xx;yy !debug
!MAT PRINT t;
LET x=INT(t(1)) !元の画素での位置
LET y=INT(t(2))
IF x<1 OR x>w OR y<1 OR y>h THEN !範囲内なら
ELSE
LET q(xx,yy)=p(x,y)
END IF
CASE ELSE !NOP
END SELECT
NEXT xx
NEXT yy
MAT PLOT CELLS, IN 0,1; 1,0 :q !画像を表示する
END
●モザイク
OPTION ARITHMETIC NATIVE !CPUパワー
SET COLOR MODE "NATIVE"
GLOAD "c:\BASICw32\SAMPLE\ZENKOUJI.JPG" !画像を読み込む
ASK PIXEL SIZE (0,0; 1,1) w,h !画像の縦横の大きさ(ピクセル単位)を調べる
DIM p(w,h),q(w,h) !画像の大きさに対応する配列要素を用意する
ASK PIXEL ARRAY (0,1) p !画像の各点の色情報を配列に格納する
PRINT "画像の大きさ 縦:";h;" 横:";w
!SET BITMAP SIZE w,h !ウィンドウの大きさを画像に合わせる
LET Rx=10 !1辺の長さ
LET Ry=10
LET th=RAD(30) !方向
DIM M1(3,3),M2(3,3),M7(3,3),M8(3,3)
MAT M1=IDN !画像の中央を原点へ
LET M1(1,3)=-w/2
LET M1(2,3)=-h/2
MAT M2=IDN !方向をX軸に一致させ、半径を1とする
LET M2(1,1)=COS(th)/Rx
LET M2(1,2)=SIN(th)/Rx
LET M2(2,1)=-SIN(th)/Ry
LET M2(2,2)=COS(th)/Ry
MAT M7=IDN !INV(M2)
LET M7(1,1)=COS(th)*Rx
LET M7(1,2)=-SIN(th)*Rx
LET M7(2,1)=SIN(th)*Ry
LET M7(2,2)=COS(th)*Ry
MAT M8=IDN !INV(M1)
LET M8(1,3)=w/2
LET M8(2,3)=h/2
MAT q=ZER !黒色
!座標変換 f:(x,y)→(xx,yy)の逆変換を考える
DIM t(3)
FOR yy=1 TO h !変換後の画素位置で走査する
FOR xx=1 TO w
LET t(1)=xx !非線形変換前の線形変換
LET t(2)=yy
LET t(3)=1
MAT t=M1*t
MAT t=M2*t
!非線形変換
LET t(1)=INT(t(1))+0.5
LET t(2)=INT(t(2))+0.5
MAT t=M7*t !非線形変換後の線形変換
MAT t=M8*t
!PRINT xx;yy !debug
!MAT PRINT t;
LET x=INT(t(1)) !元の画素での位置
LET y=INT(t(2))
IF x<1 OR x>w OR y<1 OR y>h THEN !範囲内なら
ELSE
LET q(xx,yy)=p(x,y)
END IF
NEXT xx
NEXT yy
MAT PLOT CELLS, IN 0,1; 1,0 :q !画像を表示する
END
CALL red_point1
SET BEAM MODE "IMMORTAL"
LET t0=0 ! LET t0=-PI
LET t9=2*PI ! LET t9=PI
FOR t=t0 TO t9+1E-8 STEP (t9-t0)/500
CALL red_point2
WHEN EXCEPTION IN
PLOT LINES : r(t)*COS(t),r(t)*SIN(t);
! PLOT POINTS : r(t)*COS(t),r(t)*SIN(t)
USE
PLOT LINES
END WHEN
WAIT DELAY 0.01
NEXT t
PLOT LINES
SET BEAM MODE "RIGOROUS"
BEEP
PLOT TEXT ,AT (x9+x0)/2,y0 : "クリックで極座標表示,右クリックで終了"
DRAW p_coordinate(2,3) ! 極座標表示(偏角範囲(1〜2),表示位置(1〜4))
SUB red_point1
IF SGN(x0)<>SGN(x9) THEN LET rx0=0 ELSE LET rx0=MIN(ABS(x0),ABS(x9))
IF SGN(y0)<>SGN(y9) THEN LET ry0=0 ELSE LET ry0=MIN(ABS(y0),ABS(y9))
LET r1=SQR(rx0^2+ry0^2) ! 動径最小値
LET r9=SQR(MAX(ABS(x0),ABS(x9))^2+MAX(ABS(y0),ABS(y9))^2) ! 動径最大値
LET r8=r1+(r9-r1)/SQR(2) ! 赤点移動半径
LET x1=r8*COS(t0)
LET y1=r8*SIN(t0)
END SUB
SUB red_point2
LET x2=r8*COS(t)
LET y2=r8*SIN(t)
SET POINT STYLE 3
SET POINT COLOR 0
PLOT POINTS : x1,y1
SET POINT COLOR 4
PLOT POINTS : x2,y2 ! 赤点*
LET x1=x2
LET y1=y2
SET POINT STYLE 1
SET POINT COLOR 1
END SUB
END
REM 極座標軸(動径表示位置,偏角表示範囲,軸,動径目盛間隔,偏角目盛間隔)
EXTERNAL PICTURE polar(rn,tn,ag$,rs,ts)
! rn=動径表示位置(0無,1始線,2十字状,3放射状) ; tn=偏角表示範囲(0無,1[-180〜180],2[0〜360])
! ag$=軸("axis"始線のみ,"grid"円放射格子) ; rs=動径目盛間隔(>=0) ; ts=偏角目盛間隔(0<=ts<360)
ASK LINE COLOR alc
ASK LINE STYLE als
ASK TEXT COLOR atc
ASK TEXT JUSTIFY atjx$,atjy$
ASK AREA COLOR aac
SET LINE COLOR 15
SET TEXT COLOR 15
SET TEXT JUSTIFY "RIGHT","TOP"
ASK WINDOW x0,x9,y0,y9
LET r9=SQR(MAX(ABS(x0),ABS(x9))^2+MAX(ABS(y0),ABS(y9))^2) ! 動径最大値
IF SGN(x0)<>SGN(x9) THEN LET rx0=0 ELSE LET rx0=MIN(ABS(x0),ABS(x9))
IF SGN(y0)<>SGN(y9) THEN LET ry0=0 ELSE LET ry0=MIN(ABS(y0),ABS(y9))
SET LINE STYLE 1
PLOT LINES : 0,0 ; r9,0 ! 極座標始線
IF rn>=1 THEN PLOT TEXT ,AT 0,0 : STR$(0)
IF rs>0 THEN ! 動径目盛
ASK DEVICE SIZE PX,PY,S$
LET r0=rs*INT(SQR(rx0^2+ry0^2)/rs) ! 動径最小目盛
FOR r=r0 TO r9 STEP rs
IF LCASE$(ag$)="axis" OR LCASE$(ag$)="axes" THEN
PLOT LINES : r,-(y9-y0)/PY/2000 ; r,(y9-y0)/PY/2000 ! 始線目盛
ELSEIF LCASE$(ag$)="grid" THEN
SET LINE STYLE 3
DRAW CIRCLE WITH SHIFT(0,0)*SCALE(r) ! 同心円
END IF
IF rn=>1 THEN ! 動径数字あり
PLOT TEXT ,AT r,0 : STR$(r) ! 始線
IF rn>=2 THEN
PLOT TEXT ,AT 0,r : STR$(r) ! 十字状上
PLOT TEXT ,AT -r,0 : STR$(r) ! 十字状左
PLOT TEXT ,AT 0,-r : STR$(r) ! 十字状下
END IF
END IF
NEXT r
END IF
IF ts>0 THEN ! 偏角目盛
SET LINE STYLE 3
!FOR t=ts TO 360-ts+1E-6 STEP ts
FOR t=ts TO 360-1E-6 STEP ts
IF LCASE$(ag$)="grid" THEN PLOT LINES : 0,0;r9*COS(RAD(t)),r9*SIN(RAD(t)) ! 放射状破線
IF rn=3 THEN ! 動径数字放射状
FOR r=r0 TO r9 STEP rs
PLOT TEXT ,AT r*COS(RAD(t)),r*SIN(RAD(t)) : STR$(r)
NEXT r
END IF
NEXT t
IF tn>=1 THEN ! 偏角数字あり(単位;度)
LET r1=SQR(rx0^2+ry0^2) ! 動径最小値
LET r5=(r1+r9)/2 ! 偏角数字位置
IF rn=3 THEN SET TEXT BACKGROUND "OPAQUE"
!FOR t=ts TO 360-ts+1E-6 STEP ts
FOR t=ts TO 360-1E-6 STEP ts
IF MOD(t,90)<>0 OR rn<=1 OR rs=0 THEN
IF
t<=180 OR tn=2 THEN LET a=t ELSE LET a=t-360 ! a=偏角
CALL adjust(a)
PLOT TEXT ,AT r5*COS(RAD(t)),r5*SIN(RAD(t)) : STR$(a)
END IF
NEXT t
END IF
END IF
SET TEXT BACKGROUND "TRANSPARENT"
SET LINE COLOR alc
SET LINE STYLE als
SET TEXT COLOR atc
SET TEXT JUSTIFY atjx$,atjy$
SET AREA COLOR aac
SUB adjust(d) ! 偏角数字位置調整
IF ABS(d)<=67.5 OR d>=292.5 THEN
LET tj1$="LEFT"
ELSEIF ABS(d)>67.5 AND ABS(d)<112.5 OR d>247.5 AND d<292.5 THEN
LET tj1$="CENTER"
ELSE
LET tj1$="RIGHT"
END IF
IF ABS(d)<22.5 OR d>337.5 OR ABS(d)>157.5 AND d<202.5 THEN
LET tj2$="HALF"
ELSEIF d>=22.5 AND d<67.5 OR d>112.5 AND d<=157.5 THEN
LET tj2$="BASE"
ELSEIF d>=67.5 AND d<=112.5 THEN
LET tj2$="BOTTOM"
ELSEIF d>=-112.5 AND d<=-67.5 OR d>=247.5 AND d<=292.5 THEN
LET tj2$="TOP"
ELSE
LET tj2$="CAP"
END IF
SET TEXT JUSTIFY tj1$,tj2$
END SUB
END PICTURE
REM 極座標(r,θ)表示
EXTERNAL PICTURE p_coordinate(tn,p)
! マウスポインタが指す点の極座標(動径,偏角)を表示
! 左クリック(ドラッグ)で表示,右クリックで終了
! tn=偏角範囲(1[-π<θ<=π],2[0<=θ<2π]) ; p=表示位置(1右上,2左上,3左下,4右下)
ASK WINDOW x0,x9,y0,y9
ASK TEXT JUSTIFY atjx$,atjy$
ASK TEXT HEIGHT ath
ASK AREA COLOR aac
SET TEXT FONT "",10
SET AREA COLOR 0
IF SGN(x0)<>SGN(x9) THEN LET rx0=0 ELSE LET rx0=MIN(ABS(x0),ABS(x9))
IF SGN(y0)<>SGN(y9) THEN LET ry0=0 ELSE LET ry0=MIN(ABS(y0),ABS(y9))
LET r1=SQR(rx0^2+ry0^2) ! 動径最小値
LET r9=SQR(MAX(ABS(x0),ABS(x9))^2+MAX(ABS(y0),ABS(y9))^2) ! 動径最大値
LET r9d=LOG10(r9)
LET rd=LOG10((r9-r1)/2000)
IF r9d>0 THEN LET u$=REPEAT$("-",CEIL(r9d)-1)&"%" ELSE LET u$="%"
IF rd<0 THEN LET u$=u$&"."&REPEAT$("#",CEIL(ABS(rd)))
CALL position
DO
MOUSE POLL mx,my,ml,mr
IF ml=1 THEN
LET r=SQR(mx^2+my^2) ! 動径
WHEN EXCEPTION IN
LET t=ANGLE(mx,my) ! 偏角(-π<t<=π)
IF tn=2 AND t<0 THEN LET t=t+2*PI ! 偏角(0<=t<2π)
USE
LET r,t=0 ! 特異点(極)
END WHEN
LET
r$=USING$(u$,r)
! 動径
LET t$=USING$("-%.####",t) ! 偏角
LET d$=USING$("---%.##",DEG(t)) ! (度)
PLOT AREA : x1,y1;x2,y1;x2,y2;x1,y2
PLOT TEXT ,AT x1,y1 : r$&" "&t$&"("&d$&"°)"
END IF
WAIT DELAY 0.01 ! CPU負荷軽減
LOOP UNTIL mr=1 ! 右クリックで終了
SET TEXT JUSTIFY atjx$,atjy$
SET TEXT HEIGHT ath
SET AREA COLOR aac
SUB position ! 表示位置
ASK TEXT WIDTH(REPEAT$("W",LEN(u$)+20)) atw
LET x1=x9
LET x2=x9-atw
LET y1=y9
LET y2=y9-1.1*ath
SELECT CASE p
CASE 1 ! 画面右上
SET TEXT JUSTIFY "RIGHT","TOP"
CASE 2 ! 画面左上
SET TEXT JUSTIFY "LEFT","TOP"
LET x1=x0
LET x2=x0+atw
CASE 3 ! 画面左下
SET TEXT JUSTIFY "LEFT","BOTTOM"
LET x1=x0
LET x2=x0+atw
LET y1=y0
LET y2=y0+1.1*ath
CASE 4 ! 画面右下
SET TEXT JUSTIFY "RIGHT","BOTTOM"
LET y1=y0
LET y2=y0+1.1*ath
END SELECT
END SUB
END PICTURE
!-------------------------------
LET E=10
LET R1=1000
LET L1=20
LET L2=20
LET R2=1000
LET M=SQR(L1*L2) !結合係数 k=1
!
LET b=1
LET w=2*PI*1 !1Hz
DEF r(t)=R1*(b+SIN(w*t))
!
IF laplace_ON=1 THEN
LET R1=30
LET R2=1e9
END IF
!
!-----ルンゲ・クッタ1
DEF f1(t,i1)=( E-r(t)*i1+M*f2_ )/L1 ! f2_…直接のf2()は、不可
DEF f2(t,i2)=( M*f1_-R2*i2 )/L2 ! f1_…直接のf1()は、不可
SUB RungeKutta_1(t,i1,i2)
LET k1=f1(t,i1)
LET k2=f1(t+dt/2, i1+k1*dt/2)
LET k3=f1(t+dt/2, i1+k2*dt/2)
LET k4=f1(t+dt, i1+k3*dt )
LET i1=i1+(k1+2*k2+2*k3+k4)*dt/6
LET f1_=f1(t,i1) ! f1_…f1()のバッファ
!
LET k1=f2(t,i2)
LET k2=f2(t+dt/2, i2+k1*dt/2)
LET k3=f2(t+dt/2, i2+k2*dt/2)
LET k4=f2(t+dt, i2+k3*dt )
LET i2=i2+(k1+2*k2+2*k3+k4)*dt/6
LET f2_=f2(t,i2) ! f2_…f2()のバッファ
END SUB
SUB RungeKutta_2(t,i21)
LET k1=f21(t,i21)
LET k2=f21(t+dt/2, i21+k1*dt/2)
LET k3=f21(t+dt/2, i21+k2*dt/2)
LET k4=f21(t+dt, i21+k3*dt )
LET i21=i21+(k1+2*k2+2*k3+k4)*dt/6
END SUB
!-----ラプラス逆変換
DIM Xr(5)
! xr(0)=0 …根は6個、0は自明で因数分解から除いた。
LET Xr(1)=-R1*b/L1
LET Xr(2)=COMPLEX(0,w)
LET Xr(3)=COMPLEX(-R1*b/L1,w)
LET Xr(4)=COMPLEX(0,-w)
LET Xr(5)=COMPLEX(-R1*b/L1,-w)
FOR j=1 TO 5
PRINT Xr(j)
NEXT j
DEF Gs(s)=E/L1*( (s^2+w^2)*((s+R1*b/L1)^2+w^2) -R1/L1*s*w*(2*s+R1*b/L1) )*EXP(s*t)
DEF k_0=Gs(0 )/
(
(0 -Xr(1))*(0 -Xr(2))*(0 -Xr(3))*(0 -Xr(4))*(0 -Xr(5))
)
DEF k_1=Gs(Xr(1))/ (
Xr(1) *(Xr(1)-Xr(2))*(Xr(1)-Xr(3))*(Xr(1)-Xr(4))*(Xr(1)-Xr(5))
)
DEF k_2=Gs(Xr(2))/ (
Xr(2)*(Xr(2)-Xr(1)) *(Xr(2)-Xr(3))*(Xr(2)-Xr(4))*(Xr(2)-Xr(5))
)
DEF k_3=Gs(Xr(3))/ (
Xr(3)*(Xr(3)-Xr(1))*(Xr(3)-Xr(2)) *(Xr(3)-Xr(4))*(Xr(3)-Xr(5))
)
DEF k_4=Gs(Xr(4))/ (
Xr(4)*(Xr(4)-Xr(1))*(Xr(4)-Xr(2))*(Xr(4)-Xr(3)) *(Xr(4)-Xr(5))
)
DEF k_5=Gs(Xr(5))/ (
Xr(5)*(Xr(5)-Xr(1))*(Xr(5)-Xr(2))*(Xr(5)-Xr(3))*(Xr(5)-Xr(4))
)
DEF k0_5=re(k_0+k_1+k_2+k_3+k_4+k_5) !留数の和
!-----run
SET TEXT background "OPAQUE"
DIM baki(10),bakv(10) ! drawing channels
!
FOR dt=0.0105 TO 0.000499 STEP -0.001 !演算ピッチ sec. pitch time
IF laplace_ON=1 THEN LET dt=.0005
SET DRAW mode hidden
CLEAR
SET DRAW mode explicit
LET t=0 !計算開始 sec. calculation start
LET ts=0 !描画開始 sec. drawing start
LET tw=3 !描画時間 sec. drawing time
LET Vw=28 !+目盛上限(上側グラフ)1の倍数、Volt.Ampere. maximum scale
LET ofs=15 !+目盛上限(下側グラフ)5の倍数、Under_Graph offset !CEIL(Vw/10)*5
!
LET i21= -E/R1 ! ルンゲ・クッタ2 初期値( i1=i31←i21, i2=i20←i21+i31) at t=0
LET i1=i31 !┐
LET i2=i20 !┼ルンゲ・クッタ1 初期値! at t=0
LET f2_=f2(t,i2) !┘
!
IF laplace_ON=1 THEN LET i21=0
!
SET WINDOW -.06*tw, tw, -Vw,Vw
SET COLOR MIX(15) .5,.5,.5
DRAW grid(1,5)
PLOT TEXT,AT .1,Vw*0.92,USING"計算間隔=#.###### 秒。 計算開始後###.### 秒からの描画":dt,ts
PLOT TEXT,AT .1,Vw*0.86,USING"ω=#.##rad/s E=##V L1=##H L2=##H k=1 R1=####Ω R2=####Ω":w,E,L1,L2,R1,R2
PLOT TEXT,AT .1,-0.1*Vw:"r(t)="& STR$(R1)& "*("& STR$(b)& "+sinωt)"
DO
IF laplace_ON=1 THEN
!-----ラプラス
CALL Grph( "green","i1(x20mA)", K0_5*50, "gray","v1(x1V)", K0_5*r(t) , 8, 0)
ELSE
!-----ルンゲ・クッタ1
CALL Grph(
"blue","i1(x20mA)", i1*50 ,
"red","v1(x1V)",r(t)*i1 ,
1, 0)
CALL Grph( "blue","i1(x20mA)", i1*50 , "red","v1(x1V)", E-(L1*f1_-M*f2_), 2, 0)
CALL Grph(
"blue","i2(x2mA)" ,-i2*500, "red","v2(x1V)",
L2*f2_-M*f1_ , 3, ofs )
CALL Grph(
"blue","i2(x2mA)" ,-i2*500,
"red","v2(x1V)",-R2*i2
, 4, ofs )
CALL RungeKutta_1(t,i1,i2)
END IF
!-----ルンゲ・クッタ2
CALL Grph( "blue","i1(x20mA)",
i31*50 , "red","v1(x1V)", r(t)*i31
, 5, 0)
CALL Grph( "blue","i1(x20mA)", i31*50 , "red","v1(x1V)", E+L1*f21(t,i21), 6, 0)
CALL Grph( "blue","i2(x2mA)"
,-i20*500,
"red","v2(x1V)",-R2*i20
, 7, ofs)
CALL RungeKutta_2(t, i21)
!-----
LET t=t+dt
LOOP UNTIL ts+tw< t
NEXT dt
!-----draw
SUB Grph( icol$,i$,i, vcol$,v$,v, n, ofs)
SET WINDOW -.06*tw, tw, -Vw+ofs, Vw+ofs
IF ts< t THEN
SET LINE COLOR vcol$
PLOT LINES :t-ts-dt, bakv(n); t-ts, v
SET LINE COLOR icol$
PLOT LINES :t-ts-dt, baki(n); t-ts, i
ELSEIF t=ts THEN
SET TEXT COLOR vcol$
PLOT TEXT,AT .1, .17*Vw :v$
SET TEXT COLOR icol$
PLOT TEXT,AT .1, .11*Vw :i$
IF ofs<>0 THEN
SET LINE COLOR 15
PLOT LINES :-.06*tw, 0; tw,0
SET TEXT COLOR 15
ASK PIXEL SIZE (0,0 ;tw,Vw) px,py
FOR j=5*INT((-Vw+ofs)/5+1) TO ofs-1 STEP 5
PLOT TEXT,AT -22*tw/px, j-15*Vw/py, USING"###":j
NEXT j
END IF
SET TEXT COLOR 1
END IF
LET baki(n)=i
LET bakv(n)=v
END SUB
!スカイ・ウェイ
!-----
DIM Tr(4,4),Mv(4,4),Mp(4,4) !被写体移動、視点移動、プロジェクション変換
DIM mx(4,4),Xz(4,4),zY(4,4) !作業用、XY_Xz変換、XY_zY変換
MAT Tr=IDN
MAT Mv=IDN
!-----Y軸→Z軸 XY平面図→XZ平面図
MAT READ Xz
DATA 1,0,0,0
DATA 0,0,1,0 !Xz(2,1)=Z軸水平傾斜、Xz(2,2)=Z軸垂直傾斜
DATA 0,0,0,0
DATA 0,0,0,1 !Xz(4,2)=増設Y座標
!-----X軸→Z軸 XY平面図→ZY平面図
MAT READ zY
DATA 0,0,1,0 !zY(1,1)=Z軸水平傾斜、zY(1,2)=Z軸垂直傾斜
DATA 0,1,0,0
DATA 0,0,0,0
DATA 0,0,0,1 !zY(4,1)=増設X座標
!-----3D(X,Y,Z)→2D(X,Y)/Z プロジェクション変換 Mp(行,列)
SET WINDOW -1,1,-1,1 ! 画面スケールで、投影距離調整。
! 行列は、1に正規化した。
MAT READ Mp
DATA 1,0,0,0 !(X,Y,Z,1)→(1X,1Y,1Z,1Z) 3列目の1Z は無効。
DATA 0,1,0,0 !
DATA 0,0,1,1 ! 4列目の1Z→ 描画倍率=1/1Z で 遠近効果する。
DATA 0,0,0,0 ! (距離1への投影)
LET v0=15 ! m/s 初速度
LET a=-v0^2/2/298 ! m/s^2 減速加速度, -v0^2/2/移動距離
!
LET t0=TIME !開始
DO WHILE v(t)>0 !減速、停止するまで
LET t=TIME-t0 !経過時間を得る
IF t>tb+0.15 THEN
LET tb=t
PRINT USING "時間=###.## 速度=##.## 走行距離=###.##":t,v(t),d(t)
SET DRAW mode hidden !裏ページに書く、ちらつき防止の開始
CALL Animation( d(t)) !位置d(t)の前方描画
SET DRAW mode explicit !裏ページの表示、ちらつき防止の終了
END IF
LOOP
SUB Animation(d) !-----バス位置d の外界を描く
CLEAR
!----空
SET AREA COLOR 17
PLOT AREA:-1,0; 1,0; 1,1; -1,1
!----地
SET AREA COLOR 42
PLOT AREA:-1,0; 1,0; 1,-1; -1,-1
!----文字
SET TEXT COLOR 0
SET TEXT FONT "",90
!
!バス位置d が固定(Z=1.5m)する様に 視点dd (Z=0m)を後ろへ下げる。
!視点dd(Z=0)を中心、バス位置d(Z=1.5)を画面の枠に合わせる。投影面(Z=1.5)に射影。
!前方170m から、視点dd(Z=0)の 0.1m前方(Z=0.1)を限界に、※奥から描く
!
!----視点移動のマトリクス Mv
LET dd=d-1.5
LET Mv(4,1)=-2-yaw(d) !車道左端から2m と左右動
LET Mv(4,2)=-1.5-pitch(d) !高さ1.5m と上下動
LET Mv(4,3)=-dd !バス位置d の後方1.5m
!----
! 1 ,0 ,0 , 0|
! 0 ,1 ,0 , 0|
! 0 ,0 ,1 , 0|
!-2-yaw(d) ,-1.5-pitch(d),-dd, 1|
!----
FOR i=2.5*INT(d/2.5)+170 TO dd+0.1 STEP -2.5
! ----被写体移動のマトリクス Tr
LET Tr(4,1)=yaw(i) !左右動
LET Tr(4,2)=pitch(i) !上下動
LET Tr(4,3)=i !z座標
!----
! 1 ,0 ,0, 0|
! 0 ,1 ,0, 0|
! 0 ,0 ,1, 0|
! yaw(i) ,pitch(i) ,i, 1|
!----
MAT mx=Tr*Mv*Mp
DRAW 道路 WITH mx
IF REMAINDER(i,10) =5 THEN DRAW 街路樹 WITH mx
IF REMAINDER(i,10) =0 THEN
IF REMAINDER(i,50)=0
THEN DRAW バス停(2)WITH mx ELSE DRAW バス停(4)WITH mx !(終点=3 途中=4)
DRAW 建物(8,-9,3,3,1) WITH mx !(x,y,幅,高,奥)
DRAW 建物(-8,-9,3,3,1) WITH mx !(x,y,幅,高,奥)
END IF
NEXT i
END SUB
!パーツのサイズ。バスの位置d (Z=1.5m)で、表示倍率 1/z=1/1.5
PICTURE 建物(x,y,w,h,d1)
! ---顔面
LET zY(1,1)=d_yaw(i+w/2) !Z軸水平傾斜、カーブの微分
LET zY(1,2)=0 !d_pitch(i+w/2) !Z軸垂直傾斜、ピッチの微分
LET zY(4,1)=x !増設X軸
DRAW 前後面(y,w,h) WITH zY !元のX軸→Z軸
!---背面
LET zY(4,1)=x+d1 !増設X軸
DRAW 前後面(y,w,h) WITH zY !元のX軸→Z軸
!---屋上
LET Xz(2,1)=d_yaw(i+w/2) !Z軸水平傾斜、z軸カーブの微分
LET Xz(2,2)=0 !d_pitch(i+w/2) !Z軸垂直傾斜、z軸ピッチの微分
LET Xz(4,2)=y+h !増設Y軸
DRAW 水平面(x,w,d1) WITH Xz !元のY軸→Z軸
!---床面
LET Xz(4,2)=y !増設Y軸
DRAW 水平面(x,w,d1) WITH Xz !元のY軸→Z軸
!---側面
SET AREA COLOR 22
PLOT AREA:x,y; x+d1,y; x+d1,y+h; x,y+h
END PICTURE
!
PICTURE 前後面(y,w,h)
SET AREA COLOR 25
PLOT AREA:0,y; w,y; w,y+h; 0,y+h !(Z,Y)座標として描く。
END PICTURE
PICTURE 水平面(x,w,d1)
SET AREA COLOR 25 !26
PLOT AREA:x,0; x+d1,0; x+d1,w; x,w !(X,Z)座標として描く。
END PICTURE
PICTURE 道路
LET Xz(2,1)=d_yaw(i+2.2/2) !Z軸水平傾斜、z軸カーブの微分
LET Xz(2,2)=d_pitch(i+2.2/2) !Z軸垂直傾斜、z軸ピッチの微分
LET Xz(4,2)=0 !増設Y軸
DRAW 路面 WITH Xz !元のY軸→Z軸
!---継ぎ目線
PLOT LINES: 0,0; 2.9,0
PLOT LINES:3.1,0; 6,0
END PICTURE
PICTURE 路面
SET AREA COLOR 15
PLOT AREA:0,0; 6,0; 6,2.2; 0,2.2 !(X,Z)座標として描く。
END PICTURE
PICTURE 街路樹
SET AREA COLOR 12 !幹
PLOT AREA:-0.075,0; 0.075,0; 0.025,3; -0.025,3
SET AREA COLOR 10 !葉
FOR w=1 TO 7
DRAW disk WITH SCALE(0.3+0.05-RND*0.1)*SHIFT(0.4-RND*0.8, 2.7+0.325-RND*0.75)
NEXT W
END PICTURE
PICTURE バス停(c)
SET AREA COLOR c
PLOT AREA:-0.025,0; 0.025,0; 0.025,2; -0.025,2
DRAW disk WITH SCALE(0.5)*SHIFT(0,2)
PLOT TEXT,AT -.35,1.74,USING ">%%":STR$(i)
END PICTURE
INPUT PROMPT "INPUT FILE PATH =":PT$ !'絶対パス
IF RIGHT$(PT$,1)<>"\" THEN LET PT$=PT$ & "\"
LET PA$=PT$
LET PT$=PT$ & "*.*" !'ワイルドカード
LET N=FILES(PT$)
IF N > 0 THEN
DIM N$(N),NAME$(N),EXT$(N)
FILE LIST PT$, N$
ELSE
PRINT "No File"
STOP
END IF
FOR I=1 TO N
FILE SPLITNAME(N$(I)) PATH$,NA$,EX$
IF POS(".WAV.WMA.MP3",UCASE$(EX$)) > 0 THEN !'拡張子判別
LET NN=NN+1
LET NAME$(NN)=NA$ !'リスト登録
LET EXT$(NN)=EX$
END IF
NEXT I
IF NN=0 THEN
PRINT "No File"
STOP
END IF
FOR I=1 TO NN !' せいぜい数十曲程度 (1曲3分×100曲=5時間 !?)
FOR J=I+1 TO NN
IF NAME$(I) > NAME$(J) THEN !'!昇順にソート
SWAP NAME$(I),NAME$(J)
SWAP EXT$(I),EXT$(J)
END IF
NEXT J
NEXT I
PRINT "ファイル数=";NN
DO
INPUT PROMPT "SAVE FILE NAME=":F$ !'拡張子(.asx) OR (.m3u)を付加すること
LOOP UNTIL UCASE$(RIGHT$(F$,3))="M3U" OR UCASE$(RIGHT$(F$,3))="ASX"
OPEN #1:NAME F$
SELECT CASE UCASE$(RIGHT$(F$,3))
CASE "M3U"
FOR I=1 TO NN
PRINT #1:PA$;NAME$(I);EXT$(I) !'絶対パス指定
NEXT I
CASE "ASX"
PRINT #1:CHR$(60);"asx version = ";CHR$(34);"3.0";CHR$(34);" ";CHR$(62)
FOR I=1 TO NN
PRINT #1:CHR$(9);CHR$(60);"entry";CHR$(62)
PRINT #1:CHR$(9);CHR$(9);CHR$(60);"title";CHR$(62);NAME$(I);CHR$(60);"/title";CHR$(62)
PRINT
#1:CHR$(9);CHR$(9);CHR$(60);"ref href =
";CHR$(34);PA$;NAME$(I);EXT$(I);CHR$(34);" /";CHR$(62)
PRINT #1:CHR$(9);CHR$(60);"/entry";CHR$(62)
NEXT I
PRINT #1:CHR$(60);"/asx";CHR$(62)
END SELECT
CLOSE #1
END
RANDOMIZE
DEF FNF(X, Y) = A * X + B * Y - E
DEF FNG(X, Y) = C * X + D * Y - F
LET A=INT(RND*10)+1
LET B=INT(RND*10)+1
LET C=INT(RND*10)+1
LET D=INT(RND*10)+1
LET E=INT(RND*10)-5
LET F=INT(RND*10)-5
PRINT A;"* X +";B;"* Y=";E
PRINT C;"* X +";D;"* Y=";F
LET XH = 100
LET XL = -XH
DO
LET XM = (XH + XL) / 2
LET YM = (F - C * XM) / D !' G(X,Y)=0 を Y=GG(X)の形に変形し、XMを代入
LET YH = (F - C * XH) / D !' G(X,Y)=0 を Y=GG(X)の形に変形し、XHを代入
IF FNF(XM, YM) * FNF(XH, YH) < 0 THEN LET XL = XM ELSE LET XH = XM
LOOP UNTIL ABS(FNF(XM, YM)) < 1E-8 AND ABS(FNG(XM, YM)) < 1E-8
PRINT "X,Y="; XM; YM
PRINT "X,Y=";(D*E-B*F)/(A*D-B*C);(A*F-C*E)/(A*D-B*C) !'検算
END
OPTION CHARACTER BYTE
LET X=1/3
PRINT CVS(FLOAT2STR$(X,8,23)) !'float 32bit
PRINT STR2FLOAT(PACKDBL$(X),11,52) !'double 64bit
PRINT STR2FLOAT(FLOAT2STR$(X,15,64),15,64) !'long double 80bit
END
EXTERNAL FUNCTION AND(X,Y)
LET XO=X
LET YO=Y
LET A=1
LET S=0
FOR I=0 TO 31
LET XX=MOD(XO,2)
LET YY=MOD(YO,2)
IF YY+XX=2 THEN LET S=S+A
LET XO=INT(XO/2)
LET YO=INT(YO/2)
LET A=A*2
NEXT I
LET AND=S
END FUNCTION
EXTERNAL FUNCTION CVS(A$)
!'IEEE754 32bit str to float
OPTION CHARACTER BYTE
OPTION BASE 0
DIM B(32)
LET A$=LEFT$(A$,4)
LET K = 0
FOR I = 4 TO 1 STEP -1
LET D$ = MID$(A$, I, 1)
FOR J = 0 TO 7
IF AND(ORD(D$),2 ^ (7 -
J))<>0 THEN LET B(K) = 1 ELSE LET B(K) = 0
LET K = K + 1
NEXT J
NEXT I
FOR I = 1 TO 8
LET E = E + B(I) * 2 ^ (8 - I)
NEXT I
LET E=E-127
FOR I = 9 TO 31
LET S = S + B(I) * 2 ^ (8 - I)
NEXT I
LET X=2^E*(S+1)
IF B(0)=1 THEN LET X=-X
LET CVS=X
END FUNCTION
EXTERNAL FUNCTION MKS$(X)
!'IEEE754 32bit float to str
OPTION CHARACTER BYTE
OPTION BASE 0
DIM B(32)
IF X < 0 THEN LET B(0)=1
IF X<>0 THEN
IF ABS(X) < 1 THEN
DO WHILE 2^(N+1) > ABS(X)
LET N=N-1
LOOP
LET N=N+1
ELSE
DO WHILE 2^(N+1) < ABS(X)
LET N=N+1
LOOP
END IF
LET NN=N
LET N=N+127
FOR I=1 TO 8
IF AND(N,2^(8-I))<>0 THEN LET B(I)=1
NEXT I
LET T=(ABS(X)-2^NN)/2^NN
FOR I=9 TO 31
LET T=T*2
IF T >= 1 THEN
LET B(I)=1
LET T=T-INT(T)
END IF
NEXT I
END IF
LET AA$=CHR$(B(0)*128+B(1)*64+B(2)*32+B(3)*16+B(4)*8+B(5)*4+B(6)*2+B(7))
LET BB$=CHR$(B(8)*128+B(9)*64+B(10)*32+B(11)*16+B(12)*8+B(13)*4+B(14)*2+B(15))
LET CC$=CHR$(B(16)*128+B(17)*64+B(18)*32+B(19)*16+B(20)*8+B(21)*4+B(22)*2+B(23))
LET DD$=CHR$(B(24)*128+B(25)*64+B(26)*32+B(27)*16+B(28)*8+B(29)*4+B(30)*2+B(31))
LET MKS$=DD$ & CC$ & BB$ & AA$
END FUNCTION
EXTERNAL FUNCTION FLOAT2STR$(X,L,M) !'可変精度浮動小数変換
!'符号(1 bit) 指数部(L bit) 仮数部(M bit)
OPTION CHARACTER BYTE
OPTION BASE 0
IF MOD(L+M+1,8)<>0 THEN EXIT FUNCTION
DIM B(1+L+M)
IF X < 0 THEN LET B(0)=1
IF X<>0 THEN
IF ABS(X) < 1 THEN
DO WHILE 2^(N+1) > ABS(X)
LET N=N-1
LOOP
LET N=N+1
ELSE
DO WHILE 2^(N+1) < ABS(X)
LET N=N+1
LOOP
END IF
FOR I=1 TO L
IF AND(N+2^(L-1)-1,2^(L-I))<>0 THEN LET B(I)=1
NEXT I
LET T=(ABS(X)-2^N)/2^N
FOR I=1+L TO 1+L+M
LET T=T*2
IF T >= 1 THEN
LET B(I)=1
LET T=T-INT(T)
END IF
NEXT I
END IF
FOR J=0 TO (1+L+M)/8-1
LET AA$=CHR$(B(8*J)*128+B(8*J+1)*64+B(8*J+2)*32+B(8*J+3)*16+B(8*J+4)*8+B(8*J+5)*4+B(8*J+6)*2+B(8*J+7))
& AA$
NEXT J
LET FLOAT2STR$=AA$
END FUNCTION
EXTERNAL FUNCTION STR2FLOAT(A$,N,M)
!'符号(1 bit) 指数部(N bit) 仮数部(M bit)
OPTION CHARACTER BYTE
OPTION BASE 0
IF MOD(N+M+1,8)<>0 THEN EXIT FUNCTION
DIM B(1+N+M)
LET K=0
FOR I=INT((1+N+M)/8) TO 1 STEP -1
LET D$=MID$(A$, I, 1)
FOR J=0 TO 7
IF AND(ORD(D$),2^(7-J))<>0 THEN LET B(K)=1
LET K=K+1
NEXT J
NEXT I
FOR I=1 TO N
LET E=E+B(I)*2^(N-I)
NEXT I
LET E=E-(2^(N-1)-1)
FOR I=1+N TO 1+N+M
LET S=S+B(I)*2^(N-I)
NEXT I
LET X=2^E*(1+S)
IF B(0)=1 THEN LET X=-X
LET STR2FLOAT=X
END FUNCTION
!'TT=1-T
!'(TT+T)^(N-1) N=点の数 (0 <= T <= 1)
CALL GINIT(640,400)
RANDOMIZE
INPUT PROMPT "点の数 =": N !' N > 1
DIM X(N), Y(N)
FOR I = 1 TO N
LET X(I) = INT(RND * 640)
LET Y(I) = INT(RND * 400)
CALL CIRCLEFULL (X(I),Y(I),6,I)
NEXT I
FOR T = 0 TO 1 STEP 1 / 256
LET XX = 0
LET YY = 0
LET TT=(1-T)
SELECT CASE N
CASE 2
LET XX = TT*X(1)+T*X(2)
LET YY = TT*Y(1)+T*Y(2)
CASE 3
LET XX = TT^2*X(1)+2*TT*T*X(2)+T^2*X(3)
LET YY = TT^2*Y(1)+2*TT*T*Y(2)+T^2*Y(3)
!'CASE 4
!' LET XX = TT^3*X(1)+3*TT^2*T*X(2)+3*TT*T^2*X(3)+T^3*X(4)
!' LET YY = TT^3*Y(1)+3*TT^2*T*Y(2)+3*TT*T^2*Y(3)+T^3*Y(4)
!'CASE 5
!' LET XX =
TT^4*X(1)+4*TT^3*T*X(2)+6*TT^2*T^2*X(3)+4*TT*T^3*X(4)+T^4*X(5)
!' LET YY =
TT^4*Y(1)+4*TT^3*T*Y(2)+6*TT^2*T^2*Y(3)+4*TT*T^3*Y(4)+T^4*Y(5)
CASE ELSE
FOR I=1 TO N
LET XX=XX+TT^(N-I)*T^(I-1)*X(I)*COMB(N-1,I-1)
LET YY=YY+TT^(N-I)*T^(I-1)*Y(I)*COMB(N-1,I-1)
NEXT I
END SELECT
IF T = 0 THEN
LET XA=XX
LET YA=YY
END IF
CALL LINE(XA,YA,XX,YY,7)
LET XA=XX
LET YA=YY
NEXT T
IF N=4 THEN
SET COLOR 1
PLOT BEZIER: X(1), Y(1) ; X(2), Y(2) ; X(3), Y(3); X(4), Y(4) !'ラインが一致する
END IF
END
EXTERNAL SUB GINIT(XSIZE,YSIZE)
SET BITMAP SIZE XSIZE,YSIZE
SET WINDOW 0 , XSIZE-1 , YSIZE-1, 0
SET POINT STYLE 1
SET COLOR MIX(0) 0,0,0
SET COLOR MIX(1) 0,0,1
SET COLOR MIX(2) 1,0,0
SET COLOR MIX(3) 1,0,1
SET COLOR MIX(4) 0,1,0
SET COLOR MIX(5) 0,1,1
SET COLOR MIX(6) 1,1,0
SET COLOR MIX(7) 1,1,1
CLEAR
END SUB
EXTERNAL SUB LINE(XS,YS,XE,YE,C)
SET COLOR C
PLOT LINES: XS,YS;XE,YE
END SUB
EXTERNAL SUB CIRCLEFULL (X0, Y0, R, C)
LET X = R
LET D = X
LET Y = 0
DO WHILE X >= Y
CALL LINE (X0 - X, Y0 + Y,X0 + X, Y0 + Y, C)
CALL LINE (X0 - X, Y0 - Y,X0 + X, Y0 - Y, C)
CALL LINE (X0 - Y, Y0 + X,X0 + Y, Y0 + X, C)
CALL LINE (X0 - Y, Y0 - X,X0 + Y, Y0 - X, C)
LET D = D - 2 * Y + 1
LET Y = Y + 1
IF D < 0 THEN
LET D = D + 2 * X - 2
LET X = X - 1
END IF
LOOP
END SUB
RANDOMIZE
LET XSIZE=640 !'画像サイズ
LET YSIZE=400
CALL GINIT(XSIZE,YSIZE)
LET TH=INT(RND*90)
LET S=SIN(TH*PI/180)
LET C=COS(TH*PI/180)
LET R1=INT(RND*256)
LET R2=INT(RND*256)
LET R3=INT(RND*256)
LET R4=INT(RND*256)
LET G1=INT(RND*256)
LET G2=INT(RND*256)
LET G3=INT(RND*256)
LET G4=INT(RND*256)
LET B1=INT(RND*256)
LET B2=INT(RND*256)
LET B3=INT(RND*256)
LET B4=INT(RND*256)
LET MODE=INT(RND*40)+1
SELECT CASE INT(RND*4)
CASE 0
FOR YY=0 TO YSIZE-1
FOR XX=0 TO XSIZE-1
LET T=(C*XX+S*(YSIZE-YY))/(XSIZE*C+YSIZE*S)
LET RR=INTERPOLANT(MODE,R1,R2,T)
LET GG=INTERPOLANT(MODE,G1,G2,T)
LET BB=INTERPOLANT(MODE,B1,B2,T)
CALL PSET(XX,YY,RR,GG,BB)
NEXT XX
NEXT YY
CASE 1
LET N=INT(RND*7)+3
DIM X(N,N),Y(N),R(N),G(N),B(N)
FOR I=1 TO N
FOR J=1 TO N
LET T=(I-1)/(N-1)
LET X(I,J)=T^(N-J)
NEXT J
NEXT I
MAT X=INV(X)
FOR I=1 TO N
LET Y(I)=INT(RND*256)
NEXT I
MAT R=X*Y !'redの係数
FOR I=1 TO N
LET Y(I)=INT(RND*256)
NEXT I
MAT G=X*Y !'greenの係数
FOR I=1 TO N
LET Y(I)=INT(RND*256)
NEXT I
MAT B=X*Y !'blueの係数
FOR YY=0 TO YSIZE-1
FOR XX=0 TO XSIZE-1
LET T=(C*XX+S*(YSIZE-YY))/(XSIZE*C+YSIZE*S)
LET RR=0
LET GG=0
LET BB=0
FOR I=1 TO N !'多項式の計算
LET RR=RR*T+R(I)
LET GG=GG*T+G(I)
LET BB=BB*T+B(I)
NEXT I
CALL PSET(XX,YY,RR,GG,BB)
NEXT XX
NEXT YY
CASE 2 !'四角形
FOR YY=0 TO YSIZE-1
FOR XX=0 TO XSIZE-1
LET RR=RECTCOL(0,0,XSIZE-1,YSIZE-1,R1,R2,R3,R4,XX,YY,MODE)
LET GG=RECTCOL(0,0,XSIZE-1,YSIZE-1,G1,G2,G3,G4,XX,YY,MODE)
LET BB=RECTCOL(0,0,XSIZE-1,YSIZE-1,B1,B2,B3,B4,XX,YY,MODE)
CALL PSET(XX,YY,RR,GG,BB)
NEXT XX
NEXT YY
CASE 3 !'三角形
LET R5=INT(RND*256)
LET G5=INT(RND*256)
LET B5=INT(RND*256)
LET X1=0
LET Y1=0
LET X2=XSIZE-1
LET Y2=0
LET X3=X2
LET Y3=YSIZE-1
LET X4=0
LET Y4=YSIZE-1
LET X5=INT(XSIZE/2)
LET Y5=INT(YSIZE/2)
FOR YY=0 TO YSIZE-1
FOR XX=0 TO XSIZE-1
IF AREA3(X5,Y5,X1,Y1,X2,Y2,XX,YY)<>0 THEN
LET RR=TRIANGLECOL(X5,Y5,X1,Y1,X2,Y2,R5,R1,R2,XX,YY)
LET GG=TRIANGLECOL(X5,Y5,X1,Y1,X2,Y2,G5,G1,G2,XX,YY)
LET BB=TRIANGLECOL(X5,Y5,X1,Y1,X2,Y2,B5,B1,B2,XX,YY)
ELSEIF AREA3(X5,Y5,X2,Y2,X3,Y3,XX,YY)<>0 THEN
LET RR=TRIANGLECOL(X5,Y5,X2,Y2,X3,Y3,R5,R2,R3,XX,YY)
LET GG=TRIANGLECOL(X5,Y5,X2,Y2,X3,Y3,G5,G2,G3,XX,YY)
LET BB=TRIANGLECOL(X5,Y5,X2,Y2,X3,Y3,B5,B2,B3,XX,YY)
ELSEIF AREA3(X5,Y5,X3,Y3,X4,Y4,XX,YY)<>0 THEN
LET RR=TRIANGLECOL(X5,Y5,X3,Y3,X4,Y4,R5,R3,R4,XX,YY)
LET GG=TRIANGLECOL(X5,Y5,X3,Y3,X4,Y4,G5,G3,G4,XX,YY)
LET BB=TRIANGLECOL(X5,Y5,X3,Y3,X4,Y4,B5,B3,B4,XX,YY)
ELSEIF AREA3(X5,Y5,X4,Y4,X1,Y1,XX,YY)<>0 THEN
LET RR=TRIANGLECOL(X5,Y5,X4,Y4,X1,Y1,R5,R4,R1,XX,YY)
LET GG=TRIANGLECOL(X5,Y5,X4,Y4,X1,Y1,G5,G4,G1,XX,YY)
LET BB=TRIANGLECOL(X5,Y5,X4,Y4,X1,Y1,B5,B4,B1,XX,YY)
END IF
CALL PSET(XX,YY,RR,GG,BB)
NEXT XX
NEXT YY
END SELECT
END
EXTERNAL SUB GINIT(XSIZE,YSIZE)
SET BITMAP SIZE XSIZE,YSIZE
SET COLOR MODE "NATIVE"
CLEAR
SET POINT STYLE 1
SET WINDOW 0,XSIZE-1,YSIZE-1,0
END SUB
EXTERNAL SUB PSET(X,Y,R,G,B)
LET RR=MIN(255,MAX(0,INT(R)))
LET GG=MIN(255,MAX(0,INT(G)))
LET BB=MIN(255,MAX(0,INT(B)))
SET COLOR COLORINDEX(RR/255,GG/255,BB/255)
PLOT POINTS: X , Y
END SUB
EXTERNAL FUNCTION RECTCOL(X1,Y1,X2,Y2,C1,C2,C3,C4,X,Y,MODE)
LET P=(X-X1)/(X2-X1)
LET Q=(Y-Y1)/(Y2-Y1)
LET S1=INTERPOLANT(MODE,C1,C2,P)
LET S2=INTERPOLANT(MODE,C3,C4,Q)
LET RECTCOL=INTERPOLANT(MODE,S1,S2,Q)
END FUNCTION
EXTERNAL FUNCTION INTERPOLANT(MODE,A,B,T) !'補間式
LET T=MIN(1,MAX(0,T))
SELECT CASE MODE
CASE 1
LET V=(1-T)*A+B*T
CASE 2
LET V=(1-T)^2*A+B*T^2
CASE 3
LET V=(1-T)^3*A+B*T^3
CASE 4
LET V=(1-T)^4*A+B*T^4
CASE 5
LET V=(1-T)^5*A+B*T^5
CASE 6
LET V=(1-T^2)*A+B*T^2
CASE 7
LET V=(1-T^3)*A+B*T^3
CASE 8
IF T=1 THEN LET V=B ELSE LET V=SQR(1-T^2)*A+B*T^2
CASE 9
IF T=1 THEN LET V=B ELSE LET V=SQR(1-T^3)*A+B*T^3
CASE 10
IF T=1 THEN LET V=B ELSE LET V=SQR(1-T^2)^3*A+B*T
CASE 11
LET N=1/2
LET M=1/3
IF T=1 THEN LET V=B ELSE LET V=(1-T^M)^N*A+B*T^M
CASE 12
LET V=A*COS(PI/2*T)+B*SIN(PI/2*T)
CASE 13
LET V=A*COS(PI/2*T)^2+B*SIN(PI/2*T)^3
CASE 14
LET V=A*COS(PI/2*T^2)+B*SIN(PI/2*T^2)
CASE 15
LET V=A*(B/A)^T
CASE 16
LET V=A*EXP(T*LOG(B/A))
CASE 17
LET V=A+(B-A)*TAN(PI/4*T)
CASE 18
LET V=A+(B-A)*SIN(PI/2*T)
CASE 19
LET V=A+(B-A)*LOG(T+1)/LOG(2)
CASE 20
LET V=A+(B-A)*LOG(2*T+1)/LOG(3)
CASE 21
LET V=A+(B-A)*LOG((EXP(1)-1)*T+1)
CASE 22
LET V=A+(B-A)*(2^T-1)
CASE 23
LET V=A+(B-A)*ATN(T)*4/PI
CASE 24
IF T=0 THEN LET V=A ELSE LET V=A+(B-A)*LOG(10*T)/LOG(10)
CASE 25
LET V=A+(B-A)*SQR(T)
CASE 26
LET V=A+(B-A)*T^(1/5)
CASE 27
LET V=A+(B-A)*T^10
CASE 28
LET V=A+(B-A)*ATN(T)*4/PI
CASE 29
LET V=A+(B-A)*ASIN(T)*2/PI
CASE 30
LET V=A+(B-A)*SIN(PI/2*T)^COS(PI/2*T)
CASE 31
LET V=A+T-1+ABS(B-A)^T
CASE 32
LET V=A+(B-A)*(1-(1-T)^T)
CASE 33
LET V=A+(B-A)*(1-(1-T)/(1+T^2))
CASE 34
LET V=A+(B-A)*(T*T*T+T*T+T)/(2*T*T+1)
CASE 35
IF T=1 THEN LET V=B ELSE LET V=A+(B-A)*SIN(PI*(1-T))/((1-T)*PI)
CASE 36
LET V=A+(B-A)*(T^3+3*T^2+2*T)/(T^2+2*T+3)
CASE 37
LET V=A+(B-A)*T^3/(T^2+T-1)
CASE 38
LET V=A+(B-A)*(4^T-1)/(2^T+1)
CASE 39
LET V=A+(B-A)*(T+T^2+T^3+T^4+T^5+T^6+T^7)/7
CASE 40
LET V=A+(B-A)*(5^T-1)/4
END SELECT
LET INTERPOLANT=V
END FUNCTION
EXTERNAL FUNCTION AREA3(X1, Y1, X2, Y2, X3, Y3, PX, PY)
LET T = TRIANGLE(X1, Y1, X2, Y2, X3, Y3)
LET A = TRIANGLE(X1, Y1, X2, Y2, PX, PY)
LET B = TRIANGLE(X2, Y2, X3, Y3, PX, PY)
LET C = TRIANGLE(X1, Y1, X3, Y3, PX, PY)
IF ABS(A + B + C - T) < 1 THEN LET AREA3 = -1 ELSE LET AREA3 = 0
END FUNCTION
EXTERNAL FUNCTION TRIANGLE(X1, Y1, X2, Y2, X3, Y3) !'三角形の面積
LET TRIANGLE = ABS(X1 * Y2 + X2 * Y3 + X3 * Y1 - X2 * Y1 - X3 * Y2 - Y3 * X1) / 2
END FUNCTION
EXTERNAL FUNCTION TRIANGLECOL(OX,OY,AX,AY,BX,BY,C1,C2,C3,X,Y)
LET A = AX - OX
LET B = BX - OX
LET C = AY - OY
LET D = BY - OY
LET PX = X - OX
LET PY = Y - OY
LET DET = A * D - B * C
IF DET = 0 THEN
EXIT FUNCTION
END IF
LET S = (D * PX - B * PY) / DET
IF S < 0 THEN
EXIT FUNCTION
END IF
LET T = (A * PY - C * PX) / DET
IF T < 0 THEN
EXIT FUNCTION
END IF
IF S + T <= 1 THEN
LET TRIANGLECOL=(1-S)*(1-T)*C1+S*C2+T*C3
END IF
END FUNCTION
PRINT CDBL$("ABCDABC123") !'半角を全角文字へ
PRINT CSNG$("あいうABCDE1231234") !'全角を半角文字へ
FOR I=1 TO 100
PRINT CDBL$(STR$(I) & ":" & NUM2ROMAN$(I))
NEXT I
END
EXTERNAL FUNCTION CDBL$(X$)
FOR I=1 TO LEN(X$)
LET F$=MID$(X$,I,1)
RESTORE
DO
READ A$,AA$
LOOP UNTIL A$="" OR F$=A$
IF A$="" THEN LET AA$=F$
LET L$=L$ & AA$
NEXT I
LET CDBL$=L$
DATA A,A,B,B,C,C,D,D,E,E,F,F,G,G,H,H,I,I,J,J,K,K,L,L,M,M,N,N,O,O,P,P,Q,Q,R,R,S,S,T,T,U,U,V,V,W,W,X,X,Y,Y,Z,Z
DATA a,a,b,b,c,c,d,d,e,e,f,f,g,g,h,h,i,i,j,j,k,k,l,l,m,m,n,n,o,o,p,p,q,q,r,r,s,s,t,t,u,u,v,v,w,w,x,x,y,y,z,z
DATA 0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9
DATA
"!",!,"#",#,"$",$,"%",%,"&",&,"'",’,"(",
(,")",),"=",=,"~",〜,"+",+,"-",−,"*",*,"/",/,".",.,"<",<,">",>,"?",?,";",;,":",:,"@",@,"\",¥
DATA " "," "
DATA "",""
END FUNCTION
EXTERNAL FUNCTION CSNG$(X$)
FOR I=1 TO LEN(X$)
LET F$=MID$(X$,I,1)
RESTORE
DO
READ A$,AA$
LOOP UNTIL A$="" OR F$=AA$
IF A$="" THEN LET A$=F$
LET L$=L$ & A$
NEXT I
LET CSNG$=L$
DATA A,A,B,B,C,C,D,D,E,E,F,F,G,G,H,H,I,I,J,J,K,K,L,L,M,M,N,N,O,O,P,P,Q,Q,R,R,S,S,T,T,U,U,V,V,W,W,X,X,Y,Y,Z,Z
DATA a,a,b,b,c,c,d,d,e,e,f,f,g,g,h,h,i,i,j,j,k,k,l,l,m,m,n,n,o,o,p,p,q,q,r,r,s,s,t,t,u,u,v,v,w,w,x,x,y,y,z,z
DATA 0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9
DATA
"!",!,"#",#,"$",$,"%",%,"&",&,"'",’,"(",
(,")",),"=",=,"~",〜,"+",+,"-",−,"*",*,"/",/,".",.,"<",<,">",>,"?",?,";",;,":",:,"@",@,"\",¥
DATA " "," "
DATA "",""
END FUNCTION
EXTERNAL FUNCTION NUM2ROMAN$(X) !'(アラビア)数字 to ローマ数字(1以上4000未満)
LET R$=""
IF X < 4000 AND X > 0 THEN
OPTION BASE 0
DIM T$(4,9)
FOR I=1 TO 3
FOR J=1 TO 9
READ T$(I,J)
NEXT J
NEXT I
DATA I,II,III,IV,V,VI,VII,VIII,IX
DATA X,XX,XXX,XL,L,LX,LXX,LXXX,XC
DATA C,CC,CCC,CD,D,DC,DCC,DCCC,CM
FOR J=1 TO 3
READ T$(4,J)
NEXT J
DATA M,MM,MMM,MMMM
LET A$=LTRIM$(STR$(INT(X)))
FOR I=LEN(A$) TO 1 STEP -1
LET J=VAL(MID$(A$,LEN(A$)-I+1,1))
LET R$=R$ & T$(I,J)
NEXT I
END IF
LET NUM2ROMAN$=R$
END FUNCTION
RANDOMIZE
LET NUM$="0123456789"
!' LET NUM$="0123456789abcdef"
DO
INPUT PROMPT "桁数=": N !' 4〜5桁程度
LOOP UNTIL LEN(NUM$) >= N
LET T$=NUM$
FOR I = 1 TO N
LET R = INT(RND * LEN(T$))+1 !'乱数で1文字ずつ決める
LET ANS$=ANS$ & MID$(T$,R,1)
LET T$=LEFT$(T$,R-1) & RIGHT$(T$,LEN(T$)-R) !'選ばれた数字は候補から消す
NEXT I
PRINT N;"桁の数字を入力して下さい。 "
PRINT "GIVE UP は '*' です。"
LET COUNT=1
DO
DO
LET FL=0
PRINT COUNT; "回目 ";
INPUT PROMPT "NUMBER = ": S$
!' LET S$=LCASE$(S$)
IF ANS$ = S$ THEN
PRINT "大当たり !!"
STOP
ELSEIF S$ = "*" THEN
PRINT "正解は"; ANS$; "でした。"
STOP
ELSEIF S$ = "/" THEN
IF LEN(SS$)=N AND H > 0 THEN
PRINT "ヒント ";
FOR I=1 TO N
IF MID$(SS$,I,1)=MID$(ANS$,I,1) THEN PRINT MID$(ANS$,I,1); ELSE PRINT
"?";
NEXT I
PRINT
LET SS$=""
LET COUNT = COUNT + 1
END IF
LET FL=1
ELSEIF LEN(S$)<>N THEN
PRINT N;"桁の数字ではありません"
LET FL=1
ELSE
FOR I=1 TO N
IF POS(NUM$,MID$(S$,I,1))=0 THEN
PRINT "無効な文字があります"
LET FL=1
EXIT FOR
END IF
NEXT I
END IF
LOOP UNTIL FL=0
LET H = 0
LET C = 0
FOR I = 1 TO N
IF MID$(S$,I,1) = MID$(ANS$,I,1) THEN LET H = H + 1 !'数字と位(位置)が一致
FOR J = 1 TO N
IF I <> J AND
MID$(S$,I,1) = MID$(ANS$,J,1) THEN LET C = C + 1
!'数字は一致するが位(位置)が違う
NEXT J
NEXT I
PRINT "ヒット";H; " チップ"; C
LET COUNT = COUNT + 1
LET SS$=S$
LOOP
END
OPTION BASE 0
RANDOMIZE
CALL GINIT(300,300)
SET WINDOW 0 , 3 , 3, 0
DIM X(9),Y(9),M(9),K(9,5)
FOR I=1 TO 9
READ X(I),Y(I)
NEXT I
DATA -1,1
DATA 0,1
DATA 1,1
DATA -1,0
DATA 0,0
DATA 1,0
DATA -1,-1
DATA 0,-1
DATA 1,-1
FOR I=1 TO 9
FOR J=1 TO 5
READ K(I,J)
NEXT J
NEXT I
DATA 1,2,4,0,0
DATA 1,2,3,5,0
DATA 2,3,6,0,0
DATA 1,4,7,5,0
DATA 2,4,5,6,8
DATA 3,5,6,9,0
DATA 4,7,8,0,0
DATA 5,7,8,9,0
DATA 6,8,9,0,0
!' LET KAISU=INT(RND*18)+3
INPUT PROMPT "回数=":KAISU
DIM ANS(KAISU),UNDO(KAISU)
FOR I=1 TO KAISU
LET N=INT(RND*9)+1
LET ANS(I)=N
CALL MASU(N,1)
NEXT I
CALL DISPLAY
LET L=KAISU
DO
PRINT "残り回数=";L
INPUT PROMPT "Number=":T$
IF T$="*" THEN
EXIT DO
ELSEIF T$="/" THEN
IF KK > 0 THEN
CALL MASU(UNDO(KK),1)
LET KK=KK-1
LET L=L+1
END IF
ELSEIF POS("123456789",T$) > 0 THEN
LET TE=VAL(T$)
LET KK=KK+1
LET UNDO(KK)=TE
CALL MASU(TE,-1)
LET L=L-1
END IF
CALL DISPLAY
LOOP UNTIL L=0
FOR I=1 TO 9
IF M(I)=0 THEN LET CHK=CHK+1
NEXT I
SET COLOR 7
CLEAR
IF CHK=9 THEN
SET TEXT HEIGHT 0.32
PLOT TEXT ,AT 0,1.5: "Congratulations"
ELSE
SET TEXT HEIGHT 3/5.6
PLOT TEXT ,AT 0,1.5: "Game Over"
WAIT DELAY 1.5
MAT M=ZER
FOR L=1 TO KAISU
CALL MASU(ANS(L),1)
NEXT L
CALL DISPLAY
WAIT DELAY 2
FOR L=KAISU TO 1 STEP -1
LET N=ANS(L)
PRINT "No.";KAISU-L+1;"Number=";N
CALL MASU(N,-1)
CALL DISPLAY
WAIT DELAY 1
NEXT L
END IF
SUB MASU(TE,C)
FOR J=1 TO 5
LET V=M(K(TE,J))+C
IF V < 0 THEN LET V=7
IF V > 7 THEN LET V=0
LET M(K(TE,J))=V
NEXT J
END SUB
SUB DISPLAY
FOR J=1 TO 9
CALL BOXFULL(X(J)+1,Y(J)+1,X(J)+2,Y(J)+2,M(J))
NEXT J
FOR I=1 TO 2
FOR J=1 TO 2
CALL LINE(I,0,I,3,7)
CALL LINE(0,J,3,J,7)
NEXT J
NEXT I
END SUB
END
EXTERNAL SUB GINIT(XSIZE,YSIZE)
SET BITMAP SIZE XSIZE,YSIZE
SET POINT STYLE 1
SET COLOR MODE "REGULAR"
SET COLOR MIX(0) 0,0,0
SET COLOR MIX(1) 0,0,1
SET COLOR MIX(2) 1,0,0
SET COLOR MIX(3) 1,0,1
SET COLOR MIX(4) 0,1,0
SET COLOR MIX(5) 0,1,1
SET COLOR MIX(6) 1,1,0
SET COLOR MIX(7) 1,1,1
CLEAR
END SUB
EXTERNAL SUB BOXFULL(X1,Y1,X2,Y2,C)
SET COLOR C
PLOT AREA: X1,Y1;X2,Y1;X2,Y2;X1,Y2;X1,Y1
END SUB
EXTERNAL SUB LINE(XS,YS,XE,YE,C)
SET COLOR C
PLOT LINES
PLOT LINES: XS,YS;XE,YE
END SUB
OPTION BASE 0
RANDOMIZE
!' INPUT PROMPT "SIZE 横,縦=":XSIZE,YSIZE
LET XSIZE=INT(RND*7)+3
LET YSIZE=INT(RND*7)+3
CALL GINIT(80*XSIZE,80*YSIZE)
SET WINDOW 0 , XSIZE , YSIZE, 0
SET TEXT JUSTIFY "LEFT" , "HALF"
FOR I=1 TO XSIZE-1
FOR J=1 TO YSIZE-1
CALL LINE(I,0,I,YSIZE,7)
CALL LINE(0,J,XSIZE,J,7)
NEXT J
NEXT I
LET KAISU=INT(RND*10)+3
!' INPUT PROMPT "回数=":KAISU
DIM M(XSIZE,YSIZE),XX(KAISU),YY(KAISU)
DIM UNDOX(KAISU),UNDOY(KAISU)
FOR K=1 TO KAISU
LET X=INT(RND*XSIZE)
LET Y=INT(RND*YSIZE)
LET XX(K)=X
LET YY(K)=Y
CALL MASU(X,Y,1)
NEXT K
CALL DISPLAY
LET L=KAISU
DO
LET FL=0
PRINT "残り回数=";L
DO
MOUSE POLL X,Y,LEFT,RIGHT
LOOP WHILE LEFT=1 OR RIGHT=1
DO
MOUSE POLL X,Y,LEFT,RIGHT
IF GETKEYSTATE(27)<0 THEN LET FL=1
LOOP WHILE LEFT=0 AND RIGHT=0 AND FL=0
IF FL=1 THEN EXIT DO
IF RIGHT=1 THEN
IF KK > 0 THEN
LET X=UNDOX(KK)
LET Y=UNDOY(KK)
LET KK=KK-1
CALL MASU(X,Y,1)
CALL DISPLAY
LET L=L+1
END IF
ELSEIF LEFT=1 THEN
LET X=INT(X)
LET Y=INT(Y)
PRINT "X,Y=(";X;",";Y;")"
LET KK=KK+1
LET UNDOX(KK)=X
LET UNDOY(KK)=Y
CALL MASU(X,Y,-1)
LET L=L-1
CALL DISPLAY
END IF
LOOP UNTIL L=0
FOR I=0 TO XSIZE-1
FOR J=0 TO YSIZE-1
IF M(I,J)=0 THEN LET CHK=CHK+1
NEXT J
NEXT I
CLEAR
SET COLOR 7
IF CHK=XSIZE*YSIZE THEN !' ゲームクリア
SET TEXT HEIGHT XSIZE/9.375
PLOT TEXT ,AT 0,YSIZE/2: "Congratulations"
ELSE
SET TEXT HEIGHT XSIZE/5.6
PLOT TEXT ,AT 0,YSIZE/2: "Game Over"
WAIT DELAY 1.5
MAT M=ZER
FOR K=1 TO KAISU
CALL MASU(XX(K),YY(K),1)
NEXT K
CALL DISPLAY
WAIT DELAY 2
FOR K=KAISU TO 1 STEP -1 !'解答の表示
CALL MASU(XX(K),YY(K),-1)
PRINT "No.";KAISU-K+1;" X,Y=(";XX(K);",";YY(K);")"
CALL DISPLAY
WAIT DELAY 1
NEXT K
END IF
SUB MASU(X,Y,C)
FOR I=-1 TO 1
FOR J=-1 TO 1
IF X+I >= 0 AND Y+J
>= 0 AND X+I < XSIZE AND Y+J < YSIZE AND I*J=0 THEN
LET V=M(X+I,Y+J)+C
IF V < 0 THEN LET V=7
IF V > 7 THEN LET V=0
LET M(X+I,Y+J)=V
END IF
NEXT J
NEXT I
END SUB
SUB DISPLAY !'画面表示
FOR I=0 TO XSIZE-1
FOR J=0 TO YSIZE-1
CALL BOXFULL(I,J,I+1,J+1,M(I,J))
NEXT J
NEXT I
FOR I=1 TO XSIZE-1
FOR J=1 TO YSIZE-1
CALL LINE(I,0,I,YSIZE,7)
CALL LINE(0,J,XSIZE,J,7)
NEXT J
NEXT I
END SUB
END
EXTERNAL SUB GINIT(XSIZE,YSIZE)
SET BITMAP SIZE XSIZE,YSIZE
SET POINT STYLE 1
SET COLOR MODE "REGULAR"
SET COLOR MIX(0) 0,0,0
SET COLOR MIX(1) 0,0,1
SET COLOR MIX(2) 1,0,0
SET COLOR MIX(3) 1,0,1
SET COLOR MIX(4) 0,1,0
SET COLOR MIX(5) 0,1,1
SET COLOR MIX(6) 1,1,0
SET COLOR MIX(7) 1,1,1
CLEAR
END SUB
EXTERNAL SUB BOXFULL(X1,Y1,X2,Y2,C)
SET COLOR C
PLOT AREA: X1,Y1;X2,Y1;X2,Y2;X1,Y2;X1,Y1
END SUB
EXTERNAL SUB LINE(XS,YS,XE,YE,C)
SET COLOR C
PLOT LINES
PLOT LINES: XS,YS;XE,YE
END SUB
DECLARE EXTERNAL FUNCTION COMB
PUBLIC NUMERIC MAXSIZE,MSIZE,B(20),EPS
PUBLIC STRING T$(20),TT$(20)
DIM A(20),C(20),TI$(20),TEMP(20) !'個数は10〜15程度を想定
LET N=1
LET EPS=0
LET SUM=0
DO
INPUT PROMPT "数値(" & STR$(N) & ") ":A(N) !'(ファイルサイズ、演奏時間等)
IF A(N)=0 THEN !' 0で入力終了
LET N=N-1
EXIT DO
END IF
LET SUM=SUM+A(N)
!' INPUT PROMPT "タイトル(" & STR$(N) & ") ":T$(N) !'(ファイル名、曲名等)
LET N=N+1
LOOP
INPUT PROMPT "目標値=":MAXSIZE !'(メディア容量、空き容量等)
IF MAXSIZE >= SUM THEN
CALL DISPLAY(N,A,T$)
STOP
END IF
!' INPUT PROMPT "許容範囲=":EPS !'目標値 - 合計値 <= 許容範囲 となる組み合わせの表示
LET MMIN=MAXSIZE
LET K=0
DO
LET K=K+1
FOR I=1 TO N
IF A(I) >= MAXSIZE/K THEN EXIT DO
NEXT I
LOOP UNTIL K=N
FOR R=K TO N-1
LET MSIZE=MAXSIZE
MAT TEMP=ZER
LET RR=R
CALL COMB(A,N,RR,TEMP,1)
IF MSIZE < MMIN THEN
LET MMIN=MSIZE
MAT C=B
MAT TI$=TT$
END IF
NEXT R
IF MMIN > 0 THEN CALL DISPLAY(N,C,TI$)
END
EXTERNAL SUB COMB(X(),N,R,A(),K)
IF R=0 THEN
LET S=0
FOR I=1 TO N
IF A(I)=1 THEN
LET S=S+X(I)
END IF
IF S > MAXSIZE THEN EXIT SUB
NEXT I
IF MAXSIZE >= S AND MAXSIZE-S <= MSIZE THEN
LET MSIZE=MAXSIZE-S
MAT B=ZER
MAT TT$=NUL$
LET M=0
FOR J=1 TO N
IF A(J)=1 THEN
LET M=M+1
LET B(M)=X(J)
LET TT$(M)=T$(J)
END IF
NEXT J
IF MSIZE <= EPS THEN
CALL DISPLAY(N,B,TT$)
END IF
END IF
ELSE
FOR I=K TO N-R+1
LET A(I)=1
CALL COMB(X,N,R-1,A,I+1)
LET A(I)=0
NEXT I
END IF
END SUB
EXTERNAL SUB DISPLAY(N,A(),K$())
LET S=0
FOR I=1 TO N
IF A(I)<>0 THEN
PRINT "No.";I;":";A(I);" ";K$(I)
LET S=S+A(I)
END IF
NEXT I
PRINT "計";S;"残差";MAXSIZE-S
END SUB
OPTION BASE 0
PUBLIC NUMERIC MAXLEVEL
LET MAXLEVEL=20
DIM X(MAXLEVEL),Y(MAXLEVEL)
CALL COSINE(X)
CALL SINE(Y)
PRINT "COS(SIN(X))"
CALL HORNER(X,Y)
CALL DISPLAY(X)
LET XX=.5
PRINT VALUE(X,XX);COS(SIN(XX)) !'検算
PRINT
CALL CLR(X)
LET X(0)=-1
LET X(2)=2 !'2*X^2-1 COS 2倍角式
CALL REPEATFUNC(X,4) !'COS 2^4倍角式
PRINT "F(F(F(F(X))))"
CALL DISPLAY(X)
LET XX=COS(RAD(30)/2^4)
PRINT VALUE(X,XX);F(F(F(F(XX)))) !'検算
PRINT COS(RAD(30))
PRINT
CALL COSINE(X)
CALL RCPFUNC(X) !'逆数
PRINT "1/COS(X)"
CALL DISPLAY(X)
LET XX=.5
PRINT VALUE(X,XX);1/COS(XX) !'検算
PRINT
CALL COSINE(X)
CALL SQRFUNC(X) !'平方根
PRINT "SQR(COS(X))"
CALL DISPLAY(X)
LET XX=.5
PRINT VALUE(X,XX);SQR(COS(XX)) !'検算
PRINT
CALL COSINE(X)
LET N=SQR(2)
CALL ROOTFUNC(X,N) !'非整数乗
PRINT "COS(X)^";N
CALL DISPLAY(X)
LET XX=.5
PRINT VALUE(X,XX);COS(XX)^N !'検算
PRINT
CALL COSINE(X)
CALL SINE(Y)
CALL POWERFUNC(X,Y) !'多項式乗
PRINT "COS(X)^SIN(X)"
CALL DISPLAY(X)
LET XX=.5
PRINT VALUE(X,XX);COS(XX)^SIN(XX) !'検算
END
EXTERNAL FUNCTION F(X)
LET F=2*X*X-1 !'COS 2倍角
END FUNCTION
EXTERNAL FUNCTION VALUE(A(),XX) !'多項式 F(X)の値
LET N=DIMCHECK(A)
LET Y=A(N)
FOR I=N-1 TO 0 STEP -1
LET Y=Y*XX+A(I)
NEXT I
LET VALUE=Y
END FUNCTION
EXTERNAL SUB HORNER(F(),G())
!' 多項式 F[X}に多項式 G[X]を代入 F[G[X]]
OPTION BASE 0
DIM Y(MAXLEVEL)
LET N=DIMCHECK(F)
LET Y(0)=F(N)
FOR I=N-1 TO 0 STEP -1
CALL MUL(Y,G)
LET Y(0)=Y(0)+F(I)
NEXT I
CALL COPY(F,Y)
END SUB
EXTERNAL SUB REPEATFUNC(X(),N)
!'F[F[F[...F[X]]]]...]
OPTION BASE 0
DIM C(MAXLEVEL),T(MAXLEVEL)
CALL COPY(C,X)
CALL COPY(T,X)
FOR I=2 TO N
CALL HORNER(C,X)
CALL COPY(X,C)
CALL COPY(C,T)
NEXT I
END SUB
EXTERNAL SUB RCPFUNC(X())
!'1/(1-F[X])=1+F[X]+F[X]^2+F[X]^3+...収束半径(ABS(F[X]) < 1)
!'1/F[X]=1/(1-(1-F[X])
OPTION BASE 0
DIM C(MAXLEVEL),Y(MAXLEVEL)
LET Y(0)=1
FOR I=0 TO MAXLEVEL
LET C(I)=1 !'1+F[X]+F[X]^2+F[X]^3+...
NEXT I
CALL SUBST(Y,X) !'1-F[X]
CALL HORNER(C,Y)
CALL COPY(X,C)
END SUB
EXTERNAL SUB SQRFUNC(X())
!' SQR(1-(1-F[X])) 収束半径(ABS(F[X]) < 1)
OPTION BASE 0
DIM C(MAXLEVEL),Y(MAXLEVEL)
LET Y(0)=1
CALL SUBST(Y,X) !'1-F[X]
CALL COMB(C,1,-1,1,.5) !'(1-X)^.5
CALL HORNER(C,Y)
CALL COPY(X,C)
END SUB
EXTERNAL SUB ROOTFUNC(X(),N)
!' (1-(1-F[X]))^N 収束半径(ABS(F[X]) < 1)
OPTION BASE 0
DIM C(MAXLEVEL),Y(MAXLEVEL)
LET Y(0)=1
CALL SUBST(Y,X) !'1-F[X]
CALL COMB(C,1,-1,1,N) !'(1-X)^N
CALL HORNER(C,Y)
CALL COPY(X,C)
END SUB
EXTERNAL SUB LOGFUNC(X())
!'LOG(F[X])
OPTION BASE 0
DIM C(MAXLEVEL)
CALL LN(C)
LET X(0)=X(0)-1
CALL HORNER(C,X)
CALL COPY(X,C)
END SUB
EXTERNAL SUB EXPFUNC(X())
!'EXP(F[X])
OPTION BASE 0
DIM C(MAXLEVEL)
CALL EXPON(C)
CALL HORNER(C,X)
CALL COPY(X,C)
END SUB
EXTERNAL SUB POWERFUNC(F(),G())
!' F[X] ^ G[X] = EXP(G[X]*LOG(F[X]))
CALL LOGFUNC(F)
CALL MUL(F,G)
CALL EXPFUNC(F)
END SUB
EXTERNAL SUB DISPLAY(A())
LET N=DIMCHECK(A)
IF N > 1 THEN
IF A(N)<0 THEN PRINT "-";
IF ABS(A(N))<>1 THEN
PRINT STR$(ABS(A(N)));"*X^";STR$(N);
ELSE
PRINT "X^";STR$(N);
END IF
END IF
FOR I=N-1 TO 2 STEP -1
IF A(I)<>0 THEN
IF A(I) < 0 THEN PRINT "-"; ELSE PRINT "+";
IF ABS(A(I))<>1 THEN
PRINT STR$(ABS(A(I)));"*X^";STR$(I);
ELSEIF ABS(A(I))=1 THEN
PRINT "X^";STR$(I);
END IF
END IF
NEXT I
IF A(1)<>0 THEN
IF N > 1 THEN
IF A(1) < 0 THEN PRINT "-"; ELSE PRINT "+";
END IF
IF ABS(A(1))<>1 THEN
PRINT STR$(ABS(A(1)));"*X";
ELSEIF ABS(A(1))=1 THEN
PRINT "X";
END IF
END IF
IF A(0)<>0 THEN
IF A(0) < 0 THEN PRINT "-"; ELSE PRINT "+";
PRINT STR$(ABS(A(0)));
END IF
PRINT
END SUB
EXTERNAL SUB COMB(X(),A,B,M,N) !'二項定理 収束半径(ABS(F[X]) < 1)
!' (A+B*X^M)^N = A^N+N*A^(N-1)*B*X^M+N*(N-1)/2!*A^(N-2)*B^2*X^(2*M)+...B^N*X^(M*N)+B^N
CALL CLR(X)
LET NN=1
LET X(0)=A^N
FOR I=1 TO INT(MAXLEVEL/M)
LET NN=NN*(N-I+1)/I
LET X(M*I)=NN*A^(N-I)*B^I
NEXT I
END SUB
EXTERNAL SUB SINE(X())
!' SIN(X)
CALL CLR(X)
LET X(1)=1
LET T=1
FOR I=3 TO MAXLEVEL STEP 2
LET T=-T/(I-1)/I
LET X(I)=T
NEXT I
END SUB
EXTERNAL SUB COSINE(X())
!' COS(X)
CALL CLR(X)
LET X(0)=1
LET T=1
FOR I=2 TO MAXLEVEL STEP 2
LET T=-T/(I-1)/I
LET X(I)=T
NEXT I
END SUB
EXTERNAL SUB EXPON(X())
!' EXP(X)
LET X(0)=1
LET T=1
FOR I=1 TO MAXLEVEL
LET T=T/I
LET X(I)=T
NEXT I
END SUB
EXTERNAL SUB LN(X())
!'LOG(1+X)
LET X(0)=0
FOR I=1 TO MAXLEVEL
IF MOD(I,2)=1 THEN LET X(I)=1/I ELSE LET X(I)=-1/I
NEXT I
END SUB
EXTERNAL SUB SUBST(Y(),X())
FOR I=0 TO MAXLEVEL
LET Y(I)=Y(I)-X(I)
NEXT I
END SUB
EXTERNAL SUB COPY(X(),Y())
FOR I=0 TO MAXLEVEL
LET X(I)=Y(I)
NEXT I
END SUB
EXTERNAL SUB MUL(Y(),X())
OPTION BASE 0
DIM C(MAXLEVEL)
FOR J=0 TO MAXLEVEL
FOR I=0 TO MAXLEVEL-J
LET C(I+J)=C(I+J)+Y(I)*X(J)
NEXT I
NEXT J
CALL COPY(Y,C)
END SUB
EXTERNAL SUB CLR(X())
FOR I=0 TO MAXLEVEL
LET X(I)=0
NEXT I
END SUB
EXTERNAL FUNCTION DIMCHECK(X())
FOR N=MAXLEVEL TO 0 STEP -1
IF X(N)<>0 THEN EXIT FOR
NEXT N
LET DIMCHECK=N
END FUNCTION
DECLARE EXTERNAL FUNCTION StrConv.ASC$ ,StrConv.JIS$ !半角、全角
DECLARE EXTERNAL FUNCTION StrConv.ToHiragana$ ,StrConv.ToKatakana$ !ひらがな、カタカナ
LET t$="BASICプログラミングーぅ〜!"
PRINT ASC$(t$) !半角へ
PRINT JIS$(ASC$(t$)) !全角へ
PRINT ToKatakana$("abcXYZあいうカキク890 *?")
PRINT ToHiragana$("abcXYZあいうカキク890 *?")
END
MODULE StrConv !文字の変換
!「半角 → 全角」対応表 ※JISコード(JIS X 0201)順
DATA " "," " !32
DATA "!","!" !33
DATA """","”" !34
DATA "#","#" !35
DATA "$","$" !36
DATA "%","%" !37
DATA "&","&" !38
DATA "'","’" !39
DATA "(","(" !40
DATA ")",")" !41
DATA "*","*" !42
DATA "+","+" !43
DATA ",","," !44
DATA "-","−" !45
DATA ".","." !46
DATA "/","/" !47
DATA "0","0" !48
DATA "1","1" !49
DATA "2","2" !50
DATA "3","3" !51
DATA "4","4" !52
DATA "5","5" !53
DATA "6","6" !54
DATA "7","7" !55
DATA "8","8" !56
DATA "9","9" !57
DATA ":",":" !58
DATA ";",";" !59
DATA "<","<" !60
DATA "=","=" !61
DATA ">",">" !62
DATA "?","?" !63
DATA "@","@" !64
DATA "A","A" !65
DATA "B","B" !66
DATA "C","C" !67
DATA "D","D" !68
DATA "E","E" !69
DATA "F","F" !70
DATA "G","G" !71
DATA "H","H" !72
DATA "I","I" !73
DATA "J","J" !74
DATA "K","K" !75
DATA "L","L" !76
DATA "M","M" !77
DATA "N","N" !78
DATA "O","O" !79
DATA "P","P" !80
DATA "Q","Q" !81
DATA "R","R" !82
DATA "S","S" !83
DATA "T","T" !84
DATA "U","U" !85
DATA "V","V" !86
DATA "W","W" !87
DATA "X","X" !88
DATA "Y","Y" !89
DATA "Z","Z" !90
DATA "[","[" !91
DATA "\","¥" !92
DATA "]","]" !93
DATA "^","^" !94
DATA "_","_" !95
DATA "`","‘" !96
DATA "a","a" !97
DATA "b","b" !98
DATA "c","c" !99
DATA "d","d" !100
DATA "e","e" !101
DATA "f","f" !102
DATA "g","g" !103
DATA "h","h" !104
DATA "i","i" !105
DATA "j","j" !106
DATA "k","k" !107
DATA "l","l" !108
DATA "m","m" !109
DATA "n","n" !110
DATA "o","o" !111
DATA "p","p" !112
DATA "q","q" !113
DATA "r","r" !114
DATA "s","s" !115
DATA "t","t" !116
DATA "u","u" !117
DATA "v","v" !118
DATA "w","w" !119
DATA "x","x" !120
DATA "y","y" !121
DATA "z","z" !122
DATA "{","{" !123
DATA "|","|" !124
DATA "}","}" !125
DATA "~","〜" !126
DATA "。","。" !161
DATA "「","「" !162
DATA "」","」" !163
DATA "、","、" !164
DATA "・","・" !165
DATA "ヲ","ヲ" !166
DATA "ァ","ァ" !167
DATA "ィ","ィ" !168
DATA "ゥ","ゥ" !169
DATA "ェ","ェ" !170
DATA "ォ","ォ" !171
DATA "ャ","ャ" !172
DATA "ュ","ュ" !173
DATA "ョ","ョ" !174
DATA "ッ","ッ" !175
DATA "ー","ー" !176
DATA "ア","ア" !177
DATA "イ","イ" !178
DATA "ウ","ウ" !179
DATA "エ","エ" !180
DATA "オ","オ" !181
DATA "カ","カ" !182
DATA "キ","キ" !183
DATA "ク","ク" !184
DATA "ケ","ケ" !185
DATA "コ","コ" !186
DATA "サ","サ" !187
DATA "シ","シ" !188
DATA "ス","ス" !189
DATA "セ","セ" !190
DATA "ソ","ソ" !191
DATA "タ","タ" !192
DATA "チ","チ" !193
DATA "ツ","ツ" !194
DATA "テ","テ" !195
DATA "ト","ト" !196
DATA "ナ","ナ" !197
DATA "ニ","ニ" !198
DATA "ヌ","ヌ" !199
DATA "ネ","ネ" !200
DATA "ノ","ノ" !201
DATA "ハ","ハ" !202
DATA "ヒ","ヒ" !203
DATA "フ","フ" !204
DATA "ヘ","ヘ" !205
DATA "ホ","ホ" !206
DATA "マ","マ" !207
DATA "ミ","ミ" !208
DATA "ム","ム" !209
DATA "メ","メ" !210
DATA "モ","モ" !211
DATA "ヤ","ヤ" !212
DATA "ユ","ユ" !213
DATA "ヨ","ヨ" !214
DATA "ラ","ラ" !215
DATA "リ","リ" !216
DATA "ル","ル" !217
DATA "レ","レ" !218
DATA "ロ","ロ" !219
DATA "ワ","ワ" !220
DATA "ン","ン" !221
DATA "゙","゛" !222
DATA "゚","゜" !223
!「全角カタカナ → 半角カタカナ」の対応表
DATA "ァ","ァ", "ア","ア", "ィ","ィ", "イ","イ", "ゥ","ゥ", "ウ","ウ", "ェ","ェ", "エ","エ", "ォ","ォ", "オ","オ"
DATA "カ","カ", "ガ","ガ", "キ","キ", "ギ","ギ", "ク","ク", "グ","グ", "ケ","ケ", "ゲ","ゲ", "コ","コ", "ゴ","ゴ"
DATA "サ","サ", "ザ","ザ", "シ","シ", "ジ","ジ", "ス","ス", "ズ","ズ", "セ","セ", "ゼ","ゼ", "ソ","ソ", "ゾ","ゾ"
DATA "タ","タ", "ダ","ダ", "チ","チ", "ヂ","ヂ", "ッ","ッ", "ツ","ツ", "ヅ","ヅ", "テ","テ", "デ","デ", "ト","ト", "ド","ド"
DATA "ナ","ナ", "ニ","ニ", "ヌ","ヌ", "ネ","ネ", "ノ","ノ"
DATA "ハ","ハ", "バ","バ", "パ","パ", "ヒ","ヒ", "ビ","ビ", "ピ","ピ", "フ","フ", "ブ","ブ", "プ","プ", "ヘ","ヘ", "ベ","ベ", "ペ","ペ", "ホ","ホ", "ボ","ボ", "ポ","ポ"
DATA "マ","マ", "ミ","ミ", "ム","ム", "メ","メ", "モ","モ"
DATA "ャ","ャ", "ヤ","ヤ", "ュ","ュ", "ユ","ユ", "ョ","ョ", "ヨ","ヨ"
DATA "ラ","ラ", "リ","リ", "ル","ル", "レ","レ", "ロ","ロ"
DATA "ヮ","ワ", "ワ","ワ", "ヰ","イ", "ヱ","エ", "ヲ","ヲ", "ン","ン", "ヴ","ヴ", "ヵ","カ", "ヶ","ケ"
SHARE STRING JisTBL$(0 TO 255), KataTBL$(9505 TO 9590)
DO
READ IF MISSING THEN EXIT DO : a$,aa$ !インデックス、変換値
IF ORD(a$)<256 THEN
LET JisTBL$(ORD(a$))=aa$ !ハッシュ表をつくる
ELSE
LET KataTBL$(ORD(a$))=aa$
END IF
LOOP
!-------------------- ここまでが初期処理
!関数、サブルーチンの定義
PUBLIC FUNCTION ASC$
EXTERNAL FUNCTION ASC$(x$) !全角文字を半角文字に変換する
LET xx$=""
FOR i=1 TO LEN(x$) !対象の文字列について
LET t=ORD(x$(i:i))
SELECT CASE t
CASE 9008 TO 9017 !数字0〜9
LET w$=CHR$(t-ORD("0")+ORD("0"))
CASE 9025 TO 9050 !英字A〜Z
LET w$=CHR$(t-ORD("Z")+ORD("Z"))
CASE 9057 TO 9082 !英字a〜z
LET w$=CHR$(t-ORD("z")+ORD("z"))
CASE 9505 TO 9590 !カタカナ
LET w$=KataTBL$(t) !変換表を参照して置き換える
CASE 8481 !記号
LET w$=" "
CASE 8490
LET w$="!"
CASE 8521
LET w$=""""
CASE 8564
LET w$="#"
CASE 8560
LET w$="$"
CASE 8563
LET w$="%"
CASE 8565
LET w$="&"
CASE 8519
LET w$="'"
CASE 8522
LET w$="("
CASE 8523
LET w$=")"
CASE 8566
LET w$="*"
CASE 8540
LET w$="+"
CASE 8484
LET w$=","
CASE 8541
LET w$="-"
CASE 8485
LET w$="."
CASE 8511
LET w$="/"
CASE 8487
LET w$=":"
CASE 8488
LET w$=";"
CASE 8547
LET w$="<"
CASE 8545
LET w$="="
CASE 8548
LET w$=">"
CASE 8489
LET w$="?"
CASE 8567
LET w$="@"
CASE 8526
LET w$="["
CASE 8559
LET w$="\"
CASE 8527
LET w$="]"
CASE 8496
LET w$="^"
CASE 8498
LET w$="_"
CASE 8518
LET w$="`"
CASE 8528
LET w$="{"
CASE 8515
LET w$="|"
CASE 8529
LET w$="}"
CASE 8513
LET w$="~"
CASE 8483 !記号 ※カタカナ
LET w$="。"
CASE 8534
LET w$="「"
CASE 8535
LET w$="」"
CASE 8482
LET w$="、"
CASE 8486
LET w$="・"
CASE 8508
LET w$="ー"
CASE 8491
LET w$="゙"
CASE 8492
LET w$="゚"
CASE ELSE
LET w$=CHR$(t) !そのまま
END SELECT
LET xx$=xx$ & w$
NEXT i
LET ASC$=xx$
END FUNCTION
PUBLIC FUNCTION JIS$
EXTERNAL FUNCTION JIS$(x$) !半角文字を全角文字に変換する
LET xx$=""
LET i=1
DO WHILE i<=LEN(x$) !対象文字を順に調べる
LET t=ORD(x$(i:i))
SELECT CASE t
CASE 32 TO 126 !記号・英数字なら
LET xx$=xx$ & JisTBL$(t) !変換表を参照して置き換える
CASE 161 TO 223 !半角カタカナなら
IF i<LEN(x$) THEN LET tt=ORD(x$(i+1:i+1)) ELSE LET tt=0
IF tt=222 AND ( (t>=182 AND t<=196) OR (t>=202 AND t<=206) ) THEN !カ〜ト、ハ〜ホの濁点
LET xx$=xx$ & CHR$(ORD(JisTBL$(t))+1) !1文字とする
LET i=i+1
ELSEIF tt=223 AND (t>=202 AND t<=206) THEN !ハ〜ホの半濁点
LET xx$=xx$ & CHR$(ORD(JisTBL$(t))+2)
LET i=i+1
ELSE
LET xx$=xx$ & JisTBL$(t)
END IF
CASE ELSE !それ以外なら
LET xx$=xx$ & CHR$(t) !そのまま
END SELECT
LET i=i+1 !次へ
LOOP
LET JIS$=xx$
END FUNCTION
PUBLIC FUNCTION ToHiragana$
EXTERNAL FUNCTION ToHiragana$(x$) !全角カタカナをひらがなに変換する
LET xx$=x$
FOR i=1 TO LEN(x$) !対象文字を順に調べる
LET t=ORD(x$(i:i))
IF t<ORD("ァ") OR t>ORD("ン") THEN
ELSE
LET xx$(i:i)=CHR$(t-ORD("ァ")+ORD("ぁ"))
END IF
NEXT i
LET ToHiragana$=xx$
END FUNCTION
PUBLIC FUNCTION ToKatakana$
EXTERNAL FUNCTION ToKatakana$(x$) !ひらがなを全角カタカナに変換する
LET xx$=x$
FOR i=1 TO LEN(x$) !対象文字を順に調べる
LET t=ORD(x$(i:i))
IF t<ORD("ぁ") OR t>ORD("ん") THEN
ELSE
LET xx$(i:i)=CHR$(t-ORD("ぁ")+ORD("ァ"))
END IF
NEXT i
LET ToKatakana$=xx$
END FUNCTION
END MODULE
DIM x(0 TO 20),y(0 TO 20),r(0 TO 20),g(0 TO 20),b(0 TO 20) !頂点の位置と色
SET WINDOW -10,10,-10,10 !表示領域
DATA 1,0,0 !色RGB
DATA 1,1,0
DATA 0,1,0
DATA 0,1,1
DATA 0,0,1
DATA 1,0,1
DATA 1,0,0
CALL PLOT.Init !※
LET x(0)=0 !始点(0,0)、終点(3,0)
LET x(1)=3
LET y(0)=0
LET y(1)=0
PICTURE L1 !横線
CALL PLOT.LINES(x,y,r,g,b) !※
END PICTURE
READ r(0),g(0),b(0) !始点の色
FOR i=1 TO 6
READ r(1),g(1),b(1) !終点の色
DRAW BAR WITH SHIFT(i*3-12,0)
LET r(0)=r(1) !次へ
LET g(0)=g(1)
LET b(0)=b(1)
NEXT i
PICTURE BAR !棒状
FOR j=8 TO -8 STEP -0.05
DRAW L1 WITH SHIFT(0,j)
NEXT j
END PICTURE
END
●サンプル2
DIM x(0 TO 20),y(0 TO 20),r(0 TO 20),g(0 TO 20),b(0 TO 20) !頂点の位置と色
SET WINDOW -10,10,-10,10 !表示領域
DATA 1,0,0 !色RGB
DATA 1,1,0
DATA 0,1,0
DATA 0,1,1
DATA 0,0,1
DATA 1,0,1
DATA 1,0,0
CALL PLOT.Init !※
LET x(0)=0 !1点目の位置(中央)
LET y(0)=0
LET r(0)=0.2 !頂点の色
LET g(0)=0.2
LET b(0)=0.2
LET x(1)=9*COS(0) !2点目
LET y(1)=9*SIN(0)
READ r(1),g(1),b(1)
FOR i=1 TO 6 !六角形 ※三角形が6つ
LET x(2)=9*COS(i*PI/3) !3点目
LET y(2)=9*SIN(i*PI/3)
READ r(2),g(2),b(2)
CALL PLOT.AREALIMIT(3, x,y, r,g,b) !※
LET x(1)=x(2) !次へ
LET y(1)=y(2)
LET r(1)=r(2)
LET g(1)=g(2)
LET b(1)=b(2)
NEXT i
END
MODULE PLOT !各頂点の色をもとに線分と凸多角形にグラデーションをかける
SET POINT STYLE 1 !マークの形状
SHARE NUMERIC Xmin(0 TO 1024),Xmax(0 TO 1024) !y座標(y行)におけるx座標の最小値、最大値 ※要調整
SHARE NUMERIC Rmin(0 TO 1024),Rmax(0 TO 1024)
SHARE NUMERIC Gmin(0 TO 1024),Gmax(0 TO 1024)
SHARE NUMERIC Bmin(0 TO 1024),Bmax(0 TO 1024)
SHARE NUMERIC ww,hh !スクリーンの位置、大きさ
EXTERNAL SUB Init !レンダリングターゲットを初期化する
SET COLOR mode "NATIVE" !RGB指定
SET TEXT font "",12 !文字サイズ
ASK WINDOW x1,x2,y1,y2 !座標系の端の座標を取得する
ASK PIXEL SIZE (x1,y1; x2,y2) ww,hh !画面の大きさ(ピクセル単位)を調べる
END SUB
EXTERNAL SUB SetPixel(x,y,c) !座標(x,y,z)に色(r,g,b)で点を描く ※PLOT POINTS: x,y と同じ
SET POINT COLOR c
PLOT POINTS: WORLDX(x), WORLDX(y) !問題座標に戻して描く
!!!PLOT POINTS: x * (x2 - x1) / ww + x1, y * (y2 - y1) / hh + y1 !問題座標に戻して描く
END SUB
PUBLIC SUB POINTS !※PLOT POINTS: x,y と同じ
EXTERNAL SUB POINTS(xx,yy,rr,gg,bb) !線分を描画する
LET x1 = PIXELX(xx)
LET y1 = PIXELY(yy)
IF (y1 >= 0) AND (y1 < hh) THEN !画面内なら
IF (x1 >= 0) AND (x1 < ww) THEN
CALL SetPixel(INT(x1),INT(y1), colorindex(rr,gg,bb))
END IF
END IF
END SUB
PUBLIC SUB LINES !※PLOT LINES: x0,y0; x1,y1 または MAT PLOT LINES,LIMIT 2: x,y と同じ
EXTERNAL SUB LINES(xx(),yy(),rr(),gg(),bb()) !線分を描画する
LET x1 = PIXELX(xx(0))
LET y1 = PIXELY(yy(0))
LET x2 = PIXELX(xx(1))
LET y2 = PIXELY(yy(1))
LET r1 = rr(0) !初期値を設定する
LET g1 = gg(0)
LET b1 = bb(0)
SET DRAW mode hidden !ちらつき防止(開始)
IF (x1 = x2) AND (y1 = y2) THEN !始点と終点が同じなら
IF (y1 >= 0) AND (y1 < hh) THEN !画面内なら
IF (x1 >= 0) AND (x1 < ww) THEN
CALL SetPixel(INT(x1),INT(y1), colorindex(r1,g1,b1))
END IF
END IF
ELSE
LET dx = x2 - x1 !相対的長さ
LET dy = y2 - y1
IF ABS(dy) < ABS(dx) THEN !xの方が増分が多い
!□□□■
!□■■□ y=l*x+mの式として考える
!■□□□
LET l = dy / dx !傾きを求める
LET dr = (rr(1) - rr(0)) / dx
LET dg = (gg(1) - gg(0)) / dx
LET db = (bb(1) - bb(0)) / dx
FOR i=0 TO dx STEP SGN(dx)
LET x = x1 + i
LET y = l * i + y1
LET r = dr * i + r1
LET g = dg * i + g1
LET b = db * i + b1
IF (y >= 0) AND (y < hh) THEN !画面内なら
IF (x >= 0) AND (x < ww) THEN
CALL SetPixel(INT(x),INT(y), colorindex(r,g,b))
END IF
END IF
NEXT i
ELSE !yの方が増分が多い
!□□■
!□■□ x=l*y+mの式として考える
!□■□
!■□□
LET l = dx / dy !傾きを求める
LET dr = (rr(1) - rr(0)) / dy
LET dg = (gg(1) - gg(0)) / dy
LET db = (bb(1) - bb(0)) / dy
FOR i=0 TO dy STEP SGN(dy)
LET x = l * i + x1
LET y = y1 + i
LET r = dr * i + r1
LET g = dg * i + g1
LET b = db * i + b1
IF (y >= 0) AND (y < hh) THEN !画面内なら
IF (x >= 0) AND (x < ww) THEN
CALL SetPixel(INT(x),INT(y), colorindex(r,g,b))
END IF
END IF
NEXT i
END IF
END IF
SET DRAW mode explicit !ちらつき防止(終了)
END SUB
PUBLIC SUB AREALIMIT !!※MAT PLOT AREA,LIMIT n: x,y と同じ
EXTERNAL SUB AREALIMIT(NumOfVtx, xx(),yy(),rr(),gg(),bb()) !凸多角形(頂点番号による面の定義)を描画する
IF NumOfVtx < 3 THEN EXIT SUB
DIM sx(0 TO NumOfVtx-1),sy(0 TO NumOfVtx-1)
FOR i=0 TO NumOfVtx-1 !問題座標からピクセル座標に変換する
LET sx(i) = PIXELX(xx(i))
LET sy(i) = PIXELY(yy(i))
!!!LET sx(i) = (xx(i) - x1) * ww / (x2 - x1)
!!!LET sy(i) = (yy(i) - y1) * hh / (y2 - y1)
NEXT i
LET top = +2147483647 !バッファの使用範囲を設定する
LET btm = -2147483648
FOR i=0 TO NumOfVtx-1
IF top > sy(i) THEN LET top = sy(i)
IF btm < sy(i) THEN LET btm = sy(i)
NEXT i
LET top = INT(top)
LET btm = INT(btm)
IF top < 0 THEN LET top = 0
IF btm > hh THEN LET btm = hh
FOR i=top TO btm-1 !最大最小バッファを初期化する
LET Xmin(i) = +2147483647
LET Xmax(i) = -2147483648
NEXT i
FOR i=0 TO NumOfVtx-2 !稜線の数だけ
CALL ScanEdge(i,i+1, sx,sy,rr,gg,bb) !稜線が描く各点を求める
NEXT i
CALL ScanEdge(NumOfVtx-1,0, sx,sy,rr,gg,bb)
SET DRAW mode hidden !ちらつき防止(開始)
FOR y=top TO btm-1 !各ライン(y座標)ごとに走査する - ラスタライズ
LET l = (Xmax(y) - Xmin(y)) + 1 !増分値を計算する
LET dr = (Rmax(y) - Rmin(y)) / l
LET dg = (Gmax(y) - Gmin(y)) / l
LET db = (Bmax(y) - Bmin(y)) / l
LET r = Rmin(y) !初期値を設定する
LET g = Gmin(y)
LET b = Bmin(y)
FOR x=Xmin(y) TO Xmax(y) !ライン上での直線を描く ※PLOT LINES: Xmin(y),y; Xmax(y),y
IF (x >= 0) AND (x < ww) THEN !画面内なら
CALL SetPixel(x,y,colorindex(r,g,b)) !問題座標に戻して描く
END IF
LET r = r + dr !次へ
LET g = g + dg
LET b = b + db
NEXT x
NEXT y
SET DRAW mode explicit !ちらつき防止(終了)
END SUB
EXTERNAL SUB ScanEdge(v1,v2, xx(),yy(),rr(),gg(),bb()) !頂点v1と頂点v2を結ぶ稜線(辺)が描く各点を求める
LET l = ABS(INT(yy(v2) - yy(v1))) + 1 !幅を計算する
LET dx = (xx(v2) - xx(v1)) / l !増分値を計算する
LET dy = (yy(v2) - yy(v1)) / l
LET dr = (rr(v2) - rr(v1)) / l
LET dg = (gg(v2) - gg(v1)) / l
LET db = (bb(v2) - bb(v1)) / l
LET x = xx(v1) !初期値を設定する
LET y = yy(v1)
LET r = rr(v1)
LET g = gg(v1)
LET b = bb(v1)
FOR i=0 TO l-1 !各ライン(y座標)ごとに
LET px = INT(x)
LET py = INT(y)
IF (py >= 0) AND (py < hh) THEN !画面内なら
IF Xmin(py) > px THEN !左端位置を記録する
LET Xmin(py) = px
LET Rmin(py) = r
LET Gmin(py) = g
LET Bmin(py) = b
END IF
IF Xmax(py) < px THEN !右端位置を記録する
LET Xmax(py) = px
LET Rmax(py) = r
LET Gmax(py) = g
LET Bmax(py) = b
END IF
END IF
LET x = x + dx !次へ
LET y = y + dy
LET r = r + dr
LET g = g + dg
LET b = b + db
NEXT i
END SUB
END MODULE
!eの9000桁
!main(){int N=9009,n=N,a[9009],x;while(--n)a[n]=1+1/n;
!for(;N>9;printf("%d",x))
!for(n=N--;--n;a[n]=x%n,x=10*a[n-1]+x/n);}
!整形すると
!main(){
! int N=9009,n=N,a[9009],x;
! while(--n)
! a[n]=1+1/n;
! for( ;N>9; printf("%d",x) )
! for( n=N--; --n; a[n]=x%n, x=10*a[n-1]+x/n );
!}
REM---> main(){
!nop
REM---> int N=9009,n=N,a[9009],x;
LET N=9009
LET n_=N !※C言語は大文字と小文字は区別される
DIM a(0 TO 9009-1) !※C言語は初期化しないため値は不定
LET x=0 !※
REM --> while(--n)
DO
LET n_=n_-1
IF n_=0 THEN EXIT DO
REM --> a[n]=1+1/n;
LET a(n_)=1+IP(1/n_)
LOOP
REM---> for(;N>9;printf("%d",x))
!nop !for(※; ; )部分
DO !for( ;※; )部分
IF NOT N>9 THEN EXIT DO
REM---> for(n=N--;--n;a[n]=x%n,x=10*a[n-1]+x/n)
LET n_=N !for(※; ; )部分
LET N=N-1
DO !for( ;※; )部分
LET n_=n_-1
IF NOT n_<>0 THEN EXIT DO
REM---> ;
LET a(n_)=REMAINDER(x,n_) !for( ; ;※)部分
LET x=10*a(n_-1)+IP(x/n_)
LOOP
PRINT x; !for( ; ;※)部分
LOOP
REM---> }
END
●サンプル2
!π
!main(){int a=1e4,c=3e3,b=c,d=0,e=0,f[3000],g=1,h=0;
!for(;b;!--b?printf("%04d",e+d/a),e=d%a,h=b=c-=15:f[b]=(d=d/g*b+a*(h?f[b]:2e3))%(g=b*2-1));}
!整形すると
!main(){
! int a=1e4,
! c=3e3,
! b=c,
! d=0,
! e=0,
! f[3000],
! g=1,
! h=0;
! for(;
! b;
! !--b?
! printf("%04d",e+d/a),
! e=d%a,
! h=b=c-=15
! :
! f[b]=(d=d/g*b+a*(h?
! f[b]
! :
! 2e3
! )
! )%(g=b*2-1)
! )
! ;
!}
REM---> main(){
!nop
REM---> int a=1e4,c=3e3,b=c,d=0,e=0,f[3000],g=1,h=0;
LET a=1E4
LET c=3E3
LET b=c
LET d=0
LET e=0
DIM f(0 TO 3000-1) !※C言語は初期化しないため値は不定
LET g=1
LET h=0
REM---> for(;b;!--b?printf("%04d",e+d/a),e=d%a,h=b=c-=15:f[b]=(d=d/g*b+a*(h?f[b]:2e3))%(g=b*2-1))
!nop !for(※; ; )部分
DO !for( ;※; )部分
IF NOT b<>0 THEN EXIT DO
REM---> ;
!for( ; ;※)部分
LET b=b-1 ! !--b?〜:〜部分
IF NOT b<>0 THEN
PRINT USING "%%%%": e+IP(d/a); !printf("%04d",e+d/a),
LET e=REMAINDER(d,a) !e=d%a,
LET AX_=c-15 !h=b=c-=15
LET h,b,c=AX_
ELSE
IF h<>0 THEN LET AX_=f(b) ELSE LET AX_=2E3 !h?〜:〜部分
LET d=IP(d/g)*b+a*AX_ !d=d/g*b+a*(〜)部分
LET g=b*2-1 !g=b*2-1部分
LET f(b)=REMAINDER(d,g) !f[b]=(〜)%(〜)
END IF
LOOP
REM---> }
END
!2の平方根の2400桁
!main(){int a=1000,b=0,c=1413,d,f[1414],n=800,k;
!for(;b<c;f[b++]=14);
!for(;n--;d+=*f*a,printf("%.3d",d/a),*f=d%a)
!for(d=0,k=c;--k;d/=b,d*=2*k-1)f[k]=(d+=f[k]*a)%(b=100*k);}
!整形すると
!main(){
! int a=1000,b=0,c=1413,d,f[1414],n=800,k;
! for( ;b<c; f[b++]=14 );
! for( ;n--; d+=*f*a,printf("%.3d",d/a),*f=d%a )
! for( d=0,k=c; --k; d/=b,d*=2*k-1 )
! f[k]=(d+=f[k]*a)%(b=100*k);
! }
REM---> main(){
!nop
REM---> int a=1000,b=0,c=1413,d,f[1414],n=800,k;
LET a=1000
LET b=0
LET c=1413
DIM f(0 TO 1414-1) !※C言語は初期化しないため値は不定
LET n=800
LET k=0 !※C言語は初期化しないため値は不定
REM---> for( ;b<c; f[b++]=14 );
!nop !for(※; ; )部分
DO !for( ;※; )部分
IF NOT b<c THEN EXIT DO
REM--> ;
LET f(b)=14 !for( ; ;※)部分
LET b=b+1
LOOP
REM---> for( ;n--; d+=*f*a,printf("%.3d",d/a),*f=d%a )
!nop !for(※; ; )部分
DO !for( ;※; )部分
IF NOT n<>0 THEN EXIT DO
LET n=n-1
REM---> for(d=0,k=c; --k; d/=b,d*=2*k-1 )
LET d=0 !for(※; ; )部分
LET k=c
DO !for( ;※; )部分
LET k=k-1
IF NOT k<>0 THEN EXIT DO
REM--> f[k]=(d+=f[k]*a)%(b=100*k);
LET d=d+f(k)*a
LET b=100*k
LET f(k)=REMAINDER(d,b)
LET d=IP(d/b) !for( ; ;※)部分
LET d=d*(2*k-1)
LOOP
LET d=d+f(0)*a !for( ; ;※)部分
PRINT USING "%%%": IP(d/a) !最小桁数3桁
LET f(0)=REMAINDER(d,a)
LOOP
REM---> }
END
結果を分数の形でほしいときは有理数モードを使います。
10 OPTION ARITHMETIC RATIONAL
20 LET t=0
30 FOR k=1 TO 1129
40 LET t=t+1/k
50 NEXT k
60 PRINT t
70 END
ただし,有理数モードはJIS規格の範囲外です。
標準BASICの範囲内でこの計算を行うプログラムを作るのは上級者向きの課題です。
!定数
DECLARE EXTERNAL NUMERIC MultiPrecision.RADIX, MultiPrecision.L2
DECLARE EXTERNAL NUMERIC MultiPrecision.c0(), MultiPrecision.c1()
!演算
DECLARE EXTERNAL FUNCTION MultiPrecision.lNum2Str$, MultiPrecision.lcomp
DECLARE EXTERNAL SUB MultiPrecision.lStr2Num, MultiPrecision.lcopy
DECLARE EXTERNAL SUB MultiPrecision.ladd, MultiPrecision.lsub
DECLARE EXTERNAL SUB MultiPrecision.lmul, MultiPrecision.ldiv
DECLARE EXTERNAL SUB MultiPrecision.llmul, MultiPrecision.ldivqr
!----------------------------------------
!Σ[k=1,n]1/k の計算
LET t0=TIME
DIM P(0 TO L2),Q(0 TO L2)
CALL lStr2Num("0",P) !t=P/Q=1
CALL lStr2Num("1",Q)
DIM T1(0 TO L2),T2(0 TO L2)
FOR k=1 TO 1129
CALL lmul(P,k, T1) !t=t+1/k=(P*k+Q)/(Q*k) 通分
CALL ladd(T1,Q, P)
CALL lmul(Q,k, T2)
CALL lcopy(T2,Q)
NEXT k
PRINT lNum2Str$(P)
PRINT lNum2Str$(Q)
DIM A(0 TO L2),B(0 TO L2)
CALL lcopy(P,A) !LET A=P !copy it
CALL lcopy(Q,B) !LET B=Q
LET c=0 !繰り返し回数 debug
DO UNTIL lcomp(B,c0)=0 !最大公約数を求める
LET c=c+1 !debug
CALL ldivqr(A,B, T1,T2) !LET R=MOD(A,B) !MOD(x,y)=x-y*INT(x/y)
CALL lcopy(B,A) !LET A=B
CALL lcopy(T2,B) !LET B=R
LOOP
PRINT "c=";c !debug
PRINT "gcd=";lNum2Str$(A) !PRINT "gcd=";A !debug
CALL ldivqr(P,A, T1,T2) !LET P=P/A !約分
CALL lcopy(T1,P)
CALL ldivqr(Q,A, T1,T2) !LET Q=Q/A
CALL lcopy(T1,Q)
PRINT "P=";lNum2Str$(P) !PRINT "P=";P !結果の表示
PRINT "Q=";lNum2Str$(Q) !PRINT "Q=";Q
PRINT TIME-t0
END
MODULE MultiPrecision !正の多桁(多倍長)整数の計算
!桁の数字の列を格納する配列a()を考える。
!上位桁 下位桁
!a(L2),a(L2-1),…,a(1),a(0) の構造で表すことができる。
!言い換えると、n進数表記の各桁がa()となる。
!たとえば、100進数とすると、a(k)は正の整数2桁(0〜99)となる。
!例. 12345は1*100*100+23*100+45だから、a(2)=1、a(1)=23、a(0)=45。
SHARE NUMERIC KETA
PUBLIC NUMERIC RADIX,L2
LET KETA=4 !桁数 1,2,3,4 ※32bitか64bit整数の範囲
LET RADIX=10^KETA !基数
LET L=3000 !求める桁数 ※
LET L2=INT(L/KETA)+1 !配列の大きさ
PUBLIC NUMERIC c0(0 TO 1000) !※
CALL lStr2Num("0",c0) !定数0
PUBLIC NUMERIC c1(0 TO 1000) !※
CALL lStr2Num("1",c1) !定数1
SHARE NUMERIC aa(0 TO 1000),bb(0 TO 1000),m(0 TO 1000) !作業用 ※
!----- 下位の演算ルーチン
PUBLIC SUB ladd
EXTERNAL SUB ladd(a(),b(), c()) !多桁+多桁 ※C=A+B
LET cy=0 !桁上がり
FOR i=0 TO L2 !下の桁から
LET d=a(i)+b(i)+cy !同じ桁で
IF d<RADIX THEN
LET c(i)=d
LET cy=0
ELSE
LET c(i)=d-RADIX
LET cy=1 !上の桁へ
END IF
NEXT i
IF cy>0 THEN
PRINT "加算オーバーフロー"
STOP
END IF
END SUB
PUBLIC SUB lsub
EXTERNAL SUB lsub(a(),b(), c()) !多桁−多桁 ※A>B、C=A-B
LET brrw=0 !借り
FOR i=0 TO L2 !下の桁から
LET d=a(i)-b(i)-brrw !同じ桁で
IF d>=0 THEN
LET c(i)=d
LET brrw=0
ELSE
LET c(i)=d+RADIX
LET brrw=1 !上の桁から借りる
END IF
NEXT i
IF brrw>0 THEN
PRINT "減算A-Bで、A>Bではありません。"
STOP
END IF
END SUB
PUBLIC SUB lmul
EXTERNAL SUB lmul(a(),b, c()) !多桁×正の整数(0〜255)※10000進数なら32767
LET cy=0
FOR i=0 TO L2 !下の桁から
LET d=a(i)*b+cy
LET cy=INT(d/RADIX) !桁上がり
LET c(i)=MOD(d,RADIX) !この桁
NEXT i
IF cy>0 THEN
PRINT "乗算オーバーフロー"
STOP
END IF
END SUB
PUBLIC SUB ldiv
EXTERNAL SUB ldiv(a(),b, c()) !多桁÷正の整数(0〜255)※10000進数なら32767
IF b=0 THEN
PRINT "0では割れません。"
STOP
END IF
LET r=0 !余り
FOR i=L2 TO 0 STEP -1 !上の桁から
LET d=a(i)+r
LET c(i)=INT(d/b) !商はこの桁
LET r=MOD(d,b)*RADIX !余りを下の桁へ
NEXT i
END SUB
PUBLIC SUB lcopy
EXTERNAL SUB lcopy(a(), b()) !コピー B=A
FOR i=0 TO L2 !mat b=a
LET b(i)=a(i) !同じ桁で
NEXT i
END SUB
PUBLIC FUNCTION lcomp
EXTERNAL FUNCTION lcomp(a(),b()) !比較 A>Bなら1、A=Bなら0、A<Bなら-1
FOR i=L2 TO 0 STEP -1 !上の桁から
IF a(i)>b(i) THEN
LET lcomp=1
EXIT FUNCTION
ELSEIF a(i)<b(i) THEN
LET lcomp=-1
EXIT FUNCTION
END IF
NEXT i
LET lcomp=0
END FUNCTION
!----- 入力、出力ルーチン
PUBLIC SUB lStr2Num
EXTERNAL SUB lStr2Num(a$, a()) !数字列を多桁整数に変換する
FOR i=0 TO L2
LET A(i)=0
NEXT i
FOR i=LEN(a$) TO 1 STEP -KETA
LET d=INT((LEN(a$)-i)/KETA)
IF d>L2 THEN
PRINT "桁数が足りません。"
STOP
END IF
LET a(d)=VAL(a$(i-KETA+1:i))
NEXT i
END SUB
PUBLIC FUNCTION lNum2Str$
EXTERNAL FUNCTION lNum2Str$(a()) !多桁整数を数字列に変換する
LET aMSD=GetMSD(a)
IF aMSD<0 THEN !0なら
LET a$=" 0"
ELSE
LET a$=" "&STR$(a(aMSD)) !1桁目
FOR i=aMSD-1 TO 0 STEP -1 !2桁目以降
LET a$=a$&right$("000"&STR$(a(i)),4)
NEXT i
END IF
LET lNum2Str$=a$
END FUNCTION
!----- 上位の演算ルーチン
PUBLIC SUB llmul
EXTERNAL SUB llmul(a(),b(), c()) !多桁×多桁 ※C=A*B
FOR i=0 TO L2*2 !mat c=zer
LET c(i)=0
NEXT i
LET aMSD=GetMSD(a)
LET bMSD=GetMSD(b)
IF aMSD<0 OR bMSD<0 THEN EXIT SUB !乗数、被乗数が0なら
FOR j=0 TO bMSD !乗数:下の桁から
LET cy=0
IF b(j)>0 THEN !0は計算しない
FOR i=0 TO aMSD !被乗数:下の桁から
LET d=a(i)*b(j)+cy + c(i+j) !累積 ※筆算参照 O(n^2)
LET c(i+j)=MOD(d,RADIX) !この桁
LET cy=INT(d/RADIX) !桁上がり
NEXT i
IF cy>0 THEN LET c(j+aMSD+1)=cy !上位桁へ
END IF
NEXT j
END SUB
EXTERNAL FUNCTION GetMSD(a()) !最上位桁の位置を得る
FOR i=L2 TO 0 STEP -1
IF a(i)<>0 THEN EXIT FOR
NEXT i
LET GetMSD=i !桁位置 ※0なら-1
END FUNCTION
PUBLIC SUB ldivqr
EXTERNAL SUB ldivqr(a(),b(), q(),r()) !多桁÷多桁 ※商q 余りr
LET bMSD=GetMSD(b)
IF bMSD<0 THEN !除数が0かどうか確認する
PRINT "0では割れません。"
STOP
END IF
FOR i=0 TO L2 !商を0とする
LET q(i)=0
NEXT i
LET v=b(bMSD) !最上位桁の値を得る
LET nk=INT(RADIX/(v+1)) !b(MSD)をRADIX/2以上にするための最小係数
IF nk>1 THEN
CALL lmul(b,nk, bb) !除数の最上位桁をRADIX/2以上、RADIX未満にする
CALL lmul(a,nk, aa) !aもnk倍する
ELSE
CALL lcopy(b, bb) !×1
CALL lcopy(a, aa)
END IF
LET t=GetMSD(bb)
DO UNTIL lcomp(aa,bb)<0 !a<bなら終了
LET s=GetMSD(aa)
IF aa(s)>=bb(t) THEN
IF CompareOffset(aa,bb,s-t)>=0 THEN !a>=b*RADIX^(s-t)を検査する
LET u=s-t !商の最上位桁位置uおよび値q(u)の候補を求める
LET q(u)=1
ELSE
LET u=s-t-1
LET q(u)=RADIX-1
END IF
ELSE
LET u=s-t-1
LET q(u)=INT( (aa(s)*RADIX+aa(s-1))/bb(t) )
END IF
CALL lmul(bb,q(u), m)
DO WHILE CompareOffset(aa,m,u)<0 !a>=m=b*q(0)を満たす最大のq(u)を求める
LET q(u)=q(u)-1
CALL lmul(bb,q(u), m)
LOOP
CALL SubOffset(aa,m, u) !a=a-b*q(u)*RADIX^u
LOOP
IF nk>1 THEN
CALL ldiv(aa,nk, r) !余り 1/nk倍
ELSE
CALL lcopy(aa, r)
END IF
END SUB
EXTERNAL FUNCTION CompareOffset(a(),b(),n) !桁をずらして比較する
LET aMSD=GetMSD(a)
LET bMSD=GetMSD(b)+n
IF aMSD>bMSD THEN
LET CompareOffset=1
ELSEIF aMSD<bMSD THEN
LET CompareOffset=-1
ELSE
FOR i=aMSD TO n STEP -1
IF a(i)>b(i-n) THEN
LET CompareOffset=1
EXIT FUNCTION
END IF
IF a(i)<b(i-n) THEN
LET CompareOffset=-1
EXIT FUNCTION
END IF
NEXT i
DO !a(aMSD)〜a(n)とb(bMSD)〜b(0)が一致する場合、
IF NOT i>=0 THEN EXIT DO !a(n-1)〜a(0)に非零のものがあれば、aの方が大きい
IF a(i)<>0 THEN
LET CompareOffset=1
EXIT FUNCTION
END IF
LET i=i-1
LOOP
LET CompareOffset=0
END IF
END FUNCTION
EXTERNAL SUB SubOffset(a(),b(),n) !桁をずらして減算 ※a=a-b*RADIX^n
LET brrw=0 !借り
LET bMSD=GetMSD(b) !最上位桁までbをひく
FOR i=0 TO bMSD
LET d=a(i+n)-b(i)-brrw !同じ桁で
IF d>=0 THEN
LET a(i+n)=d
LET brrw=0
ELSE
LET a(i+n)=d+RADIX
LET brrw=1 !上の桁から借りる
END IF
NEXT i
DO !上位桁への桁借り
IF NOT brrw<>0 THEN EXIT DO
IF a(i+n)<>0 THEN
LET a(i+n)=a(i+n)-1
LET brrw=0
ELSE
LET a(i+n)=RADIX-1
LET brrw=1
END IF
LET i=i+1
LOOP
END SUB
END MODULE
!-------------------------------
OPTION ANGLE DEGREES
LET x=-2
LET y=0
LET z=0
LET a=0.398
LET b=2
LET c=4
!-----レスラー方程式( 非線形項が、z*x 1つだけのカオス)
DEF dxdt( y,z)=-y-z ! (dx/dt)= -y -z
DEF dydt(x,y )= x+a*y ! (dy/dt)= x +a*y
DEF dzdt(x ,z)= b+z*(x-c) ! (dz/dt)= b +z*(x-c)
SUB RungeKutta
LET kx1=dxdt( y,z)
LET ky1=dydt(x,y )
LET kz1=dzdt(x ,z)
!
LET kx2=dxdt( y+ky1*dt/2 ,z+kz1*dt/2)
LET ky2=dydt(x+kx1*dt/2, y+ky1*dt/2 )
LET kz2=dzdt(x+kx1*dt/2 ,z+kz1*dt/2)
!
LET kx3=dxdt( y+ky2*dt/2 ,z+kz2*dt/2)
LET ky3=dydt(x+kx2*dt/2, y+ky2*dt/2 )
LET kz3=dzdt(x+kx2*dt/2 ,z+kz2*dt/2)
!
LET kx4=dxdt( y+ky3*dt ,z+kz3*dt)
LET ky4=dydt(x+kx3*dt, y+ky3*dt )
LET kz4=dzdt(x+kx3*dt ,z+kz3*dt)
!
LET x=x+(kx1+2*kx2+2*kx3+kx4)*dt/6
LET y=y+(ky1+2*ky2+2*ky3+ky4)*dt/6
LET z=z+(kz1+2*kz2+2*kz3+kz4)*dt/6
END SUB
!-----run
SET TEXT background "OPAQUE"
SET COLOR MIX(15) .5,.5,.5
SET POINT STYLE 1
DIM vl(12),vr(12),vb(12),vt(12) ,va(12)
DATA .8, .8, .6, .4, .2, 0 , 0 , 0 , .2, .4, .6, .8
DATA 1 , 1 , .8, .6, .4, .2, .2, .2, .4, .6, .8, 1
DATA .4, .6, .8, .8, .8, .6, .4, .2, 0 , 0 , 0 , .2
DATA .6, .8, 1 , 1 , 1 , .8, .6, .4, .2, .2, .2, .4
DATA 0, 30, 60, 90,120,150,180,-150,-120,-90,-60,-30
MAT READ vl,vr,vb,vt,va
!
CLEAR
LET dt=.03 !演算ピッチ sec. pitch time
LET t=0
DO
SET VIEWPORT .2, .8, .2, .8
SET WINDOW -7,7,-7,7! -4,6, -6,3
IF 0< t THEN
PLOT LINES:bakx,baky; x,y
ELSE
DRAW axes !grid(1,1)
FOR p=1 TO 12
PLOT LINES:0,0;8*COS(va(p)),8*SIN(va(p))
PLOT TEXT,AT 6.6*COS(va(p))-.15, 6.6*SIN(va(p))-.3 :STR$(va(p))
NEXT p
END IF
LET bakx=x
LET baky=y
CALL RungeKutta
FOR p=1 TO 12
IF ABS( va(p)-ANGLE(x,y))< 1 THEN
CALL poincare
END IF
NEXT p
LET t=t+dt
LOOP UNTIL 2000< t
SUB poincare
SET VIEWPORT vl(p),vr(p),vb(p),vt(p)
SET WINDOW -1,7,-1,7
!PLOT LINES:-1,-1;7,-1;7,7;-1,7;-1,-1
DRAW axes
PLOT POINTS: SQR(x^2+y^2),z
END SUB
!例題1 自然数の和
! def a(n)=n (n>=1) ※一般項
! t=Σ{a[k]; k=1,t>300} ※和が300を超えるとき、最小のkとその和を表示する
! print k,t
!
! ※擬似言語による表現
DEF a(n)=n !def a(n)=n (n>=1) の部分
LET t=0 !Σ{a[k]; k=1,t>300} の部分
LET k=1
DO
LET t=t+a(k)
IF t>300 THEN EXIT DO
LET k=k+1
LOOP
PRINT "k=";k, "t=";t !print k,t の部分
!例題1の別解
FOR k=1 TO 300 !上限 ∵1+2+3+ … +k
LET t=k*(k+1)/2 !和の公式 Σk
IF t>300 THEN EXIT FOR
NEXT k
PRINT "k=";k, t
!例題2
! def2 y[1]=1, y[n+1]=3*y[n]+2 (n>=1) ※隣接二項間漸化式
! print y[n=1,10] ※1〜10項を表示する
FUNCTION y(n) !def2 y[1]=1, y[n+1]=3*y[n]+2 (n>=1) の部分
local k,y0,y1
LET y1=1 !<---
IF n=1 THEN !第1項
LET y=y1
ELSE
FOR k=2 TO n !第2項以降
LET y0=y1
LET y1=3*y0+2 !<---
NEXT k
LET y=y1
END IF
END FUNCTION
FOR n=1 TO 10 !print x[n=1,10] の部分
PRINT n;y(n)
NEXT n
!!例題3 フィボナッチ数列
! def3 x[1]=0, x[2]=1, x[n+2]=x[n+1]+x[n] (n>=1) ※隣接三項間漸化式
! for n=1 to n ※周期のある数列へ
! print x[n] mod 4 ※余りを表示する
! next
FUNCTION x(n) !def3 x[1]=1, x[2]=1, x[n+2]=x[n+1]+x[n] (n>=1) の部分
local k,x0,x1,x2
LET x1=0 !<---
IF n=1 THEN !第1項
LET x=x1
ELSE
LET x2=1 !<---
IF n=2 THEN !第2項
LET x=x2
ELSE
FOR k=3 TO n !第3項以降
LET x0=x1
LET x1=x2
LET x2=x1+x0 !<---
NEXT k
LET x=x2
END IF
END IF
END FUNCTION
FOR n=1 TO 30
PRINT n; MOD(x(n+1),4) !print x[n] mod 4 の部分
NEXT n
END
FUNCTION f(n)
IF n<2 THEN
LET f=n !f(0)=0, f(1)=1
ELSE
LET f=f(n-1)+f(n-2) !f(n)=f(n-1)+f(n-2) n≧2
END IF
END FUNCTION
FOR k=0 TO 30 !1〜30項を表示する
PRINT k;f(k)
NEXT k
END
!先の、改良版。
!
!角度の窓を止め、角度を越える1番目で、採取する。(sens lead edge)
!文は読み辛くなるが、ピッチ幅広くても、採取出来、ピッチ幅に応じた
!ボケになるため、ピッチ幅の、評価が出来る。速度も速い。
!-30°(330°)度付近のボケが、取れた。
!レスラー方程式、3次元グラフ、中央の図は、上から見たxy平面。
!周囲30度 ごとに配置された12枚の図は、
!その角度での、ポアンカレ切断面( 縦:z軸、横:中心からの距離)
!-------------------------------
LET x=-3
LET y=0
LET z=0
LET a=0.398
LET b=2
LET c=4
!-----レスラー方程式( 非線形項が、z*x 1つだけのカオス。形状:メビウスの帯)
DEF dxdt( y,z)=-y-z ! (dx/dt)= -y -z
DEF dydt(x,y )= x+a*y ! (dy/dt)= x +a*y
DEF dzdt(x ,z)= b+z*(x-c) ! (dz/dt)= b +z*(x-c)
SUB RungeKutta
LET kx1=dxdt( y,z)
LET ky1=dydt(x,y )
LET kz1=dzdt(x ,z)
!
LET kx2=dxdt( y+ky1*dt/2 ,z+kz1*dt/2)
LET ky2=dydt(x+kx1*dt/2, y+ky1*dt/2 )
LET kz2=dzdt(x+kx1*dt/2 ,z+kz1*dt/2)
!
LET kx3=dxdt( y+ky2*dt/2 ,z+kz2*dt/2)
LET ky3=dydt(x+kx2*dt/2, y+ky2*dt/2 )
LET kz3=dzdt(x+kx2*dt/2 ,z+kz2*dt/2)
!
LET kx4=dxdt( y+ky3*dt ,z+kz3*dt)
LET ky4=dydt(x+kx3*dt, y+ky3*dt )
LET kz4=dzdt(x+kx3*dt ,z+kz3*dt)
!
LET x=x+(kx1+2*kx2+2*kx3+kx4)*dt/6
LET y=y+(ky1+2*ky2+2*ky3+ky4)*dt/6
LET z=z+(kz1+2*kz2+2*kz3+kz4)*dt/6
END SUB
!-----run
SET TEXT background "OPAQUE"
SET COLOR MIX(15) .5,.5,.5
SET POINT STYLE 1
OPTION ANGLE DEGREES
OPTION BASE 0
DIM vl(11),vr(11),vb(11),vt(11) ,va(11)
DATA .8, .8, .6, .4, .2, 0 , 0 , 0 , .2, .4, .6, .8
DATA 1 , 1 , .8, .6, .4, .2, .2, .2, .4, .6, .8, 1
DATA .4, .6, .8, .8, .8, .6, .4, .2, 0 , 0 , 0 , .2
DATA .6, .8, 1 , 1 , 1 , .8, .6, .4, .2, .2, .2, .4
DATA 0, 30, 60, 90,120,150,180,210,240,270,300,330
MAT READ vl,vr,vb,vt,va
!
LET dt=.02 !sec. pitch time
LET t=0
DO
SET VIEWPORT .2, .8, .2, .8
SET WINDOW -7,7,-7,7
LET xya= MOD(ANGLE(x,y),360) !xya= 0~< 360 ← 0~180~(-180)< ~< 0
IF 0< t THEN
PLOT LINES: bakx,baky; x,y
ELSE
DRAW axes
FOR i=11 TO 0 STEP -1
PLOT LINES:0,0;8*COS(va(i)),8*SIN(va(i))
PLOT TEXT,AT 6.6*COS(va(i))-.15, 6.6*SIN(va(i))-.3 :STR$(va(i))
IF xya<=va(i) THEN LET p=i ! 初期角度の va()番号 を探す。
NEXT i
END IF
!----
IF p=0 THEN
IF xya< va(1) THEN CALL poincare ! 0度の va() のみ。
ELSE
IF va(p)<=xya THEN CALL poincare ! 30~330度の va()
END IF
!----
LET bakx=x
LET baky=y
CALL RungeKutta
LET t=t+dt
LOOP UNTIL 1400< t
SUB poincare
SET VIEWPORT vl(p),vr(p),vb(p),vt(p)
SET WINDOW -1,7,-1,7
DRAW axes
PLOT POINTS: SQR(x^2+y^2),z
LET p=MOD(p+1,12) ! 次の va()番号
END SUB
! 再帰型。但し、N回後の最終写像から、N,,,2,1,0 逆順で描画される。
SUB fr(k, x,y)
IF 0< k THEN CALL fr(k-1, x1(x,y),y1(x,y))
PLOT POINTS: x,y
END SUB
! 写像の順番どうりに、0,1,2,,,N 正順番で描画。
SUB fo(N, x,y)
FOR k=0 TO N
PLOT POINTS: x,y
LET wx= x1(x,y) ! x= x1(x,y) ←本来ですが、x の変化は、次式の後に。
LET y= -x+F(wx) ! y= y1(x,y) ←本来ですが、wx で計算の節約。
LET x=wx
NEXT k
END SUB
SET TEXT FONT "MS 明朝",12
SET TEXT BACKGROUND "OPAQUE"
SET POINT STYLE 1
LET N=50000
!
LET h=20
LET xm= h*0.1
LET ym= h*0.35
SET WINDOW xm-h,xm+h, ym-h,ym+h
CALL fo(N,.1,2) ! 写像の正順で描画 0,1,2,,,N
!
LET h=30
LET xm= h*0.2
LET ym=-h*0.4
SET WINDOW xm-h,xm+h, ym-h,ym+h
PLOT TEXT,AT xm-h*0.15, ym+h*0.85:t$& " N= "& STR$(N)
PLOT TEXT,AT xm-h*0.9, ym+h*0.85:"しばらく御待ち下さい。"
CALL fr(N,.1,2) ! 最終写像から逆順で描画 N,,,2,1,0
PLOT TEXT,AT xm-h*0.9, ym+h*0.85:" 描画の終了 "
SUB RungeKutta
LET kx1=dxdt(x,y )
LET ky1=dydt(x,y,z)
LET kz1=dzdt(x,y,z)
!
LET kx2=dxdt(x+kx1*dt/2, y+ky1*dt/2 )
LET ky2=dydt(x+kx1*dt/2, y+ky1*dt/2 ,z+kz1*dt/2)
LET kz2=dzdt(x+kx1*dt/2, y+ky1*dt/2 ,z+kz1*dt/2)
!
LET kx3=dxdt(x+kx2*dt/2, y+ky2*dt/2 )
LET ky3=dydt(x+kx2*dt/2, y+ky2*dt/2 ,z+kz2*dt/2)
LET kz3=dzdt(x+kx2*dt/2, y+ky2*dt/2 ,z+kz2*dt/2)
!
LET kx4=dxdt(x+kx3*dt, y+ky3*dt )
LET ky4=dydt(x+kx3*dt, y+ky3*dt ,z+kz3*dt)
LET kz4=dzdt(x+kx3*dt, y+ky3*dt ,z+kz3*dt)
!
LET x=x+(kx1+2*kx2+2*kx3+kx4)*dt/6
LET y=y+(ky1+2*ky2+2*ky3+ky4)*dt/6
LET z=z+(kz1+2*kz2+2*kz3+kz4)*dt/6
END SUB
!-----run
OPTION ANGLE DEGREES
DIM pV1(4), pV2(4), P3D(4,4), rotx(4,4)
MAT rotx=IDN
!
LET ax=-75 ! 原点を通り、画面の水平軸での回転( x 軸とは、限らず。)
!
! 1, 0, 0, 0
! 0, cos(ax), 0, 0
! 0,-sin(ax), 1, 0
! 0, 0, 0, 1
!
LET rotx(2,2)=COS(ax)
LET rotx(3,2)=-SIN(ax)
!
LET xm=0
LET ym=20
LET h=40
SET WINDOW xm-h,xm+h,ym-h,ym+h
LET dt=.005 !sec. pitch time
!
FOR az=-45 TO 315 STEP 10 ! z軸での回転。360 度、一回り。
!----
LET x=2
LET y=1
LET z=24
!----
LET t=0
IF -45< az THEN SET DRAW mode hidden
CLEAR
PLOT TEXT,AT xm+h*.2,ym+h*.9 :"lorenz ローレンツ方程式"
DO
IF 0< t THEN
!---3D 曲線(x,y,z)
DRAW line3D( bakx,baky,bakz, x,y,z) WITH ROTATE(az)*rotx
PLOT LINES: pV1(1),pV1(2); pV2(1),pV2(2)
ELSE
! ---X 軸
DRAW line3D( -30,0,0, 30,0,0) WITH ROTATE(az)*rotx
PLOT LINES: pV1(1),pV1(2); pV2(1),pV2(2)
PLOT TEXT,AT pV2(1),pV2(2) :"(X)"
!---Y 軸
DRAW line3D( 0,-30,0, 0,30,0) WITH ROTATE(az)*rotx
PLOT LINES: pV1(1),pV1(2); pV2(1),pV2(2)
PLOT TEXT,AT pV2(1),pV2(2) :"(Y)"
!---Z 軸
DRAW line3D( 0,0,-10, 0,0,50) WITH ROTATE(az)*rotx
PLOT LINES: pV1(1),pV1(2); pV2(1),pV2(2)
PLOT TEXT,AT pV2(1),pV2(2) :"(Z)"
END IF
!----
LET bakx=x
LET baky=y
LET bakz=z
CALL RungeKutta
LET t=t+dt
LOOP UNTIL 30< t ! 100 くらいが良いのかも… 遅くなる。
SET DRAW mode explicit
NEXT az
PICTURE line3D(x1,y1,z1, x2,y2,z2)
MAT P3D=TRANSFORM !← draw ・・・ with matrix で与えられた matrix
LET pV1(1)=x1
LET pV1(2)=y1
LET pV1(3)=z1 !入力 z1 座標は、出力 x1,y1 に反映、描画される。
LET pV1(4)=1
MAT pV1=pV1*P3D !出力 z1 座標pV1(3)は、描画しない。
LET pV2(1)=x2
LET pV2(2)=y2
LET pV2(3)=z2 !入力 z2 座標は、出力 x2,y2 に反映、描画される。
LET pV2(4)=1
MAT pV2=pV2*P3D !出力 z2 座標pV2(3)は、描画しない。
END PICTURE
! 非線形項が、z*x 1つだけのカオス。形状:メビウスの帯
!-------------------------------
LET a=0.398
LET b=2
LET c=4
!-----レスラー方程式
SUB Dxyz( kx,ky,kz, x,y,z)
LET kx=-y-z ! (dx/dt)= -y -z
LET ky= x+a*y ! (dy/dt)= x +a*y
LET kz= b+z*(x-c) ! (dz/dt)= b +z*(x-c)
END SUB
SUB RungeKutta
CALL Dxyz( kx1,ky1,kz1, x,y,z)
CALL Dxyz( kx2,ky2,kz2, x+kx1*dt/2,y+ky1*dt/2,z+kz1*dt/2)
CALL Dxyz( kx3,ky3,kz3, x+kx2*dt/2,y+ky2*dt/2,z+kz2*dt/2)
CALL Dxyz( kx4,ky4,kz4, x+kx3*dt ,y+ky3*dt ,z+kz3*dt )
LET x=x+(kx1+2*kx2+2*kx3+kx4)*dt/6
LET y=y+(ky1+2*ky2+2*ky3+ky4)*dt/6
LET z=z+(kz1+2*kz2+2*kz3+kz4)*dt/6
END SUB
!-----run
OPTION CHARACTER byte !ウムラウト"o" =CHR$(246) をエラーにさせない。
OPTION ANGLE DEGREES
DIM pV(4), P3D(4,4), rotx(4,4)
!
MAT rotx=IDN ! 単位行列
LET ax=-55 ! 原点を通り、画面の水平軸での回転( x 軸とは、限らず。)
!
!(x,y,z,1)| 1, 0, 0, 0 | PLOT 座標ベクトルは、行ベクトル。
! | 0, cos(ax), 0, 0 | 4列目の1は、拡大率の逆数であるが、
! | 0,-sin(ax), 1, 0 | draw 文で、描画しないので、無視して可。
! | 0, 0, 0, 1 |
!
LET rotx(2,2)=COS(ax)
LET rotx(3,2)=-SIN(ax)
!
LET xm=0
LET ym=2
LET h=7
SET WINDOW xm-h,xm+h,ym-h,ym+h
LET dt=.05 ! sec. pitch time
LET SS=35 ! z軸回り、開始角度
LET EE=SS-360 ! +360:左回転 -360:右回転
!
FOR az=SS TO EE STEP SGN(EE-SS)*10 ! z軸、一回り360 度
MAT P3D=ROTATE(az)*rotx
!----
IF az<>SS THEN SET DRAW mode hidden
CLEAR
SET TEXT font "Courier",11
PLOT TEXT,AT xm+h*.2,ym+h*.9 :"R"& CHR$(246)& "ssler"
SET TEXT font "標準ゴシック",11
PLOT TEXT,AT xm+h*.45,ym+h*.9 :"レスラー方程式" ! PEN-off
!---座標軸
CALL axes3D( -6,0,0, 6,0,0, "(X)" )
CALL axes3D( 0,-6,0, 0,6,0, "(Y)" )
CALL axes3D( 0,0,-2, 0,0,8, "(Z)" )
!---3D 曲線
LET x=-3
LET y=0
LET z=0
FOR t=0 TO 300 STEP dt
CALL line3D(x,y,z)
CALL RungeKutta
NEXT t
SET DRAW mode explicit
NEXT az
SUB axes3D(x1,y1,z1, x2,y2,z2, a$ )
CALL line3D(x1,y1,z1)
CALL line3D(x2,y2,z2)
PLOT TEXT,AT pV(1),pV(2) :a$ ! PEN-off
END SUB
SUB line3D(x,y,z)
LET pV(1)=x
LET pV(2)=y
LET pV(3)=z !入力 z 座標は、出力 x,y に反映、描画される。
MAT pV=pV*P3D
PLOT LINES: pV(1),pV(2); !出力 z 座標pV(3)は、不要。 PEN-on
END SUB
SUB Dxyz( kx,ky,kz, x,y,z)
LET kx= (gR*(y-x) -ih(x))/C1 ! (d vC1/dt)= (gR*(vC2-vC1)-ih(vC1))/C1
LET ky= (gR*(x-y) +z )/C2 ! (d vC2/dt)= (gR*(vC1-vC2)+iL )/C2
LET kz=
-y/L
! (d iL /dt)= -vC2/L
END SUB
LET C1= 1/9 !コンデンサー (パラメーター C1~Bp)
LET C2= 1 !コンデンサー
LET L= 1/7 !インダクター
LET gR= 0.7 !Rのコンダクタンス(アドミタンスの実数部)
LET g0=-0.5 !負性抵抗回路の微分コンダクタンス(〜<-Bp +Bp<〜)
LET g1=-0.8 !負性抵抗回路の微分コンダクタンス( -Bp<〜<+Bp )
LET Bp= 1 !負性抵抗回路の、変曲点の電圧 絶対値。
!
LET x=-1e-7 !初期値 x,y,z
LET y= 1e-7
LET z= 1e-7
DATA -3,3, -3,3, -2.5,3 !座標軸の両端 xL,xH, yL,yH, zL,zH
MAT READ LH
LET xm=0 !画面中心 xm,ym
LET ym=.5 !
LET h=3.5 !画面片幅 ±h
LET dt=.01 ! pitch time
LET t99=120 ! close time
LET ax=-85 !z軸を、画面の水平軸で回転、傾ける角度
LET SS=-25 !z軸での、回転 開始角度
LET EE=SS+360 ! 回転 終了角度 +360:左回転 -360:右回転
CALL graph3D
!-----
SUB RungeKutta
CALL Dxyz( kx1,ky1,kz1, x,y,z)
CALL Dxyz( kx2,ky2,kz2, x+kx1*dt/2,y+ky1*dt/2,z+kz1*dt/2)
CALL Dxyz( kx3,ky3,kz3, x+kx2*dt/2,y+ky2*dt/2,z+kz2*dt/2)
CALL Dxyz( kx4,ky4,kz4, x+kx3*dt ,y+ky3*dt ,z+kz3*dt )
LET x=x+(kx1+2*kx2+2*kx3+kx4)*dt/6
LET y=y+(ky1+2*ky2+2*ky3+ky4)*dt/6
LET z=z+(kz1+2*kz2+2*kz3+kz4)*dt/6
END SUB
SUB graph3D
!-----run
!z軸を、画面の水平軸で回転、傾ける行列 rotx
!(x,y,z,1)| 1, 0, 0, 0 | 十進の、PLOTベクトルは、行ベクトル。
! | 0, cos(ax), 0, 0 | 4列目の1は、拡大率の逆数であるが、
! | 0,-sin(ax), 1, 0 | draw~with~ で効果する。
! | 0, 0, 0, 1 | このプログラムでは、無視して可。
LET rotx(2,2)=COS(ax)
LET rotx(3,2)=-SIN(ax)
!
SET WINDOW xm-h,xm+h,ym-h,ym+h
!
FOR az=SS TO EE STEP SGN(EE-SS)*10 ! z軸で、一回り360 度
MAT P3D=ROTATE(az)*rotx
!----
IF az<>SS THEN SET DRAW mode hidden
CLEAR
PLOT TEXT,AT xm-h*.8,ym+h*.9 :t$ ! PEN-off
!---座標軸
CALL axes3D( LH(1),0,0, LH(2),0,0, "(X)" )
CALL axes3D( 0,LH(3),0, 0,LH(4),0, "(Y)" )
CALL axes3D( 0,0,LH(5), 0,0,LH(6), "(Z)" )
!---3D 曲線
IF az=SS THEN
LET n=0
FOR t=0 TO t99 STEP dt
LET copy(n,1)=x
LET copy(n,2)=y ! 1回目(開始角度)で、3D記録を撮る。
LET copy(n,3)=z
CALL line3D(x,y,z)
CALL RungeKutta
LET n=n+1
NEXT t
ELSE
FOR n=0 TO n-1
LET x=copy(n,1)
LET y=copy(n,2) ! 2回目以降は、記録の再生で、高速描画。
LET z=copy(n,3)
CALL line3D(x,y,z)
NEXT n
END IF
SET DRAW mode explicit
NEXT az
END SUB
SUB axes3D(x1,y1,z1, x2,y2,z2, a$ )
CALL line3D(x1,y1,z1)
CALL line3D(x2,y2,z2)
PLOT TEXT,AT pV(1),pV(2) :a$ ! PEN-off
END SUB
SUB line3D(x,y,z)
LET pV(1)=x
LET pV(2)=y
LET pV(3)=z !入力 z 座標は、出力 x,y に反映、描画される。
MAT pV=pV*P3D
PLOT LINES: pV(1),pV(2); !出力 z 座標pV(3)は、不要。 PEN-on
END SUB
SUB Dxyzn( kx,ky,kz,kn, x,y,z,n)
LET kx= I(t)-120*y^3*z*(x-115) -40*n^4*(x+12) -.24*(x-10.613) ! (d V/dt)
LET ky= .1*(25-x)/(EXP((25-x)/10)-1)*(1-y) -4*EXP(-x/18)*y ! (d m/dt)
LET kz= .07*EXP(-x/20)*(1-z)
-1/(EXP((30-x)/10)+1)*z !
(d h/dt)
LET kn= .01*(10-x)/(EXP((10-x)/10)-1)*(1-n) -.125*EXP(-x/80)*n! (d n/dt)
END SUB
LET I0=20 !膜電流 パラメーター
LET A=40
LET f=.3000001
!
LET x=6.24 !初期値 x,y,z,n
LET y=.0761
LET z=.301
LET n=.519
!
DATA -15,100, -.3,1, -.04,.49 !座標軸の両端座標 xL,xH, yL,yH, zL,zH
MAT READ LH
LET Sx=1 !スケール倍率 Sx,Sy,Sz
LET Sy=50
LET Sz=200
!
LET xm=40 !画面中心 xm,ym
LET ym=52
LET hw=80 !画面幅/2 ±hw
LET dt=.05 ! pitch time
LET t99=500 ! close time
LET zox=40 !z軸と、平行な回転軸へのオフセットxy
LET zoy=20
LET ax=-75 !回転軸を、画面の水平軸で倒し、傾ける角度
LET SS=-25 !回転 開始角度
LET EE=SS+360 !回転 終了角度 +360:左回転 -360:右回転
CALL graph3D
!-----
SUB RungeKutta
CALL Dxyzn( kx1,ky1,kz1,kn1, x,y,z,n)
CALL Dxyzn( kx2,ky2,kz2,kn2, x+kx1*dt/2,y+ky1*dt/2,z+kz1*dt/2,n+kn1*dt/2)
CALL Dxyzn( kx3,ky3,kz3,kn3, x+kx2*dt/2,y+ky2*dt/2,z+kz2*dt/2,n+kn2*dt/2)
CALL Dxyzn( kx4,ky4,kz4,kn4, x+kx3*dt ,y+ky3*dt ,z+kz3*dt ,n+kn3*dt )
LET x=x+(kx1+2*kx2+2*kx3+kx4)*dt/6
LET y=y+(ky1+2*ky2+2*ky3+ky4)*dt/6
LET z=z+(kz1+2*kz2+2*kz3+kz4)*dt/6
LET n=n+(kn1+2*kn2+2*kn3+kn4)*dt/6
END SUB
SUB graph3D
!-----run
!回転軸を、画面の水平軸で倒し、傾ける行列 rotx
!(x,y,z,1)| 1, 0, 0, 0 | 十進の、PLOTベクトルは、行ベクトル。
! | 0, cos(ax), 0, 0 | 4列目の1は、拡大率の逆数、draw文 で効果。
! | 0,-sin(ax), 1, 0 | 直接の plot lines では、1 にリセットされる。
! | 0, 0, 0, 1 | 行列の計算では、平行移動を、可能にする。
LET rotx(2,2)=COS(ax) !このプログラムでは、SHIFT(,) で必要。
LET rotx(3,2)=-SIN(ax)
!
SET WINDOW xm-hw,xm+hw,ym-hw,ym+hw
!
FOR az=SS TO EE STEP SGN(EE-SS)*10 ! 回転軸で、10 度づつ回す。
MAT P3D=SHIFT(-zox,-zoy)*ROTATE(az)*SHIFT(zox,zoy)*rotx
!----
IF az<>SS THEN SET DRAW mode hidden
CLEAR
PLOT TEXT,AT xm-hw*.9,ym+hw*.90 :t$
PLOT TEXT,AT xm-hw*.9,ym+hw*.83 :t2$
PLOT TEXT,AT xm-hw*.9,ym-hw*.92 :t5$
PLOT TEXT,AT xm-hw*.9,ym-hw*.99 :t4$& " "& t3$ ! PEN-off
!---座標軸
CALL axes3D( LH(1),0,0, LH(2),0,0, STR$(LH(2))& "( X)" )
CALL axes3D( 0,LH(3),0, 0,LH(4),0, STR$(LH(4))& "( Y)" )
CALL axes3D( 0,0,LH(5), 0,0,LH(6), STR$(LH(6))& "( Z)" )
!---3D 曲線
IF az=SS THEN
LET ci=0
FOR t=0 TO t99 STEP dt
LET copy(ci,1)=x
LET copy(ci,2)=y ! 1回目(開始角度)で、3D記録を撮る。
LET copy(ci,3)=z
! PRINT x;y;z;n ! データーを保存したい時。
CALL line3D(x,y,z)
CALL RungeKutta
LET ci=ci+1
NEXT t
ELSE
FOR ci=0 TO ci-1 ! 2回目以降は、記録の再生で、高速描画。
CALL line3D( copy(ci,1),copy(ci,2),copy(ci,3) )
NEXT ci
END IF
SET DRAW mode explicit
NEXT az
END SUB
SUB axes3D(x1,y1,z1, x2,y2,z2, a$ )
CALL line3D(x1,y1,z1)
CALL line3D(x2,y2,z2)
PLOT TEXT,AT pV(1),pV(2) :a$ ! PEN-off
END SUB
SUB line3D(x,y,z)
LET pV(1)=x*Sx !描画目盛は、全方向等しくないと、回転で、形が保てない。
LET pV(2)=y*Sy !スケール Sx,Sy,Sz の違いは、入力の倍率として、行なう。
LET pV(3)=z*Sz !入力 z 座標は、出力 x,y に反映、描画される。
MAT pV=pV*P3D
PLOT LINES: pV(1),pV(2); ! PEN-on
END SUB
10 LET c=.0000001
20 SET WINDOW -5,5,7-c,7
30 DRAW GRID2(1,c/10) ! <-----
40 END
50 MERGE "grid2.lib" ! <----- ※EXTERNAL PICTURE 文による直接の記述もOK
また、DRAW circle、DRAW disk についても同じ現象が発生する。
SET WINDOW -500,500,-500,500
LET phi=(1+SQR(5))/2 !黄金比
LET a=2*PI*phi !黄金角
LET r=1
LET th=0
FOR i=0 TO 900
LET r=1.1*r !らせん状
LET th=th+a
LET x1=r*COS(th)
LET y1=r*SIN(th)
!DRAW disk WITH SCALE(r*0.3)*SHIFT(x1,y1)
DRAW circle WITH SCALE(r*0.3)*SHIFT(x1,y1)
NEXT i
END
MERGE "circle.lib"
!●その1 1≦p^2≦n、1≦q≦nを満たすp,qの積が、式n=p^2*qを満たす
LET n=324
FOR p=INT(SQR(n)) TO 1 STEP -1 !p^2の候補
LET x=p^2
FOR q=1 TO n !qの候補
!FOR q=1 TO n/x !qの候補 ※q=n/p^2より
IF x*q=n THEN !式を満たす
PRINT "p=";p; "q=";q
END IF
NEXT q
NEXT p
!★その2−1 n=p^2*qより、p^2はnの約数(nはp^2の倍数)
LET n=324
FOR p=INT(SQR(n)) TO 1 STEP -1 !候補を大きい方から
LET x=p^2
IF MOD(n,x)=0 THEN !p^2はnの約数より
!IF INT(n/x)*x=n THEN !nはp^2の倍数より
LET q=n/x
PRINT "p=";p; "q=";q
END IF
NEXT p
!●その2−2 n=p^2*qより、qはnの約数(nはqの倍数)
LET n=324
FOR q=1 TO n !候補を小さい方から
IF MOD(n,q)=0 THEN !qはnの約数より
!IF INT(n/q)*q=n THEN !nはqの倍数より
LET p=SQR(n/q)
IF p=INT(p) THEN !pは自然数
PRINT "p=";p; "q=";q
END IF
END IF
NEXT q
!★その3−1 n=p^2*qより、qの1次方程式q=n/p^2を解く
LET n=324
FOR p=INT(SQR(n)) TO 1 STEP -1 !約数p^2の候補を大きい方から
LET q=n/p^2
IF q=INT(q) THEN !qは自然数より
PRINT "p=";p; "q=";q
END IF
NEXT p
!●その3−2 n=p^2*qより、pの2次方程式p^2=n/qを解く
LET n=324
FOR q=1 TO n !約数qの候補を小さい方から
LET x=n/q
IF x=INT(x) THEN !pは自然数より、x=n/q=p^2は自然数
LET p=SQR(x)
IF p=INT(p) THEN !同様に、p=SQR(n/q)は自然数
PRINT "p=";p; "q=";q
END IF
END IF
NEXT q
!★その4 素因数分解 n=2^a*3^b*5^c* …とすると、a=INT(a/2)*2+MOD(a,2)、b,c,…も同様
LET n=324
LET p=1
LET q=1
LET x=n
LET m=2
DO WHILE x>1 !1まで繰り返す
LET K=0
DO WHILE MOD(x,m)=0 !mで割り切れるなら(mは因数)
LET x=x/m !割り切れるまで(m^Kの形)
LET K=K+1
LOOP
PRINT m;"^";K !debug
LET p=p*m^INT(K/2) !商
LET q=q*m^MOD(K,2) !余り
IF m>2 THEN !2,3,5,7,9,・・・で調べる
LET m=m+2
ELSE
LET m=m+1
END if
LOOP
PRINT "p=";p; "q=";q
END
!平方根の計算
!p*SQR(q)を、「SQR(q)とその係数p」として、配列a(q)=pで表せる。
!∵n=p^2*q、n,p,q≧0とすると、SQR(n)=p*SQR(q)と変形できる。
! これより、SQR(32)=4*SQR(2)となり、同類項をまとめる場合、共通項SQR(2)として扱える。
! また、SQR()を配列として解釈すると、SQR(n)を一意に表現できる。
LET szRt=10 !扱う平方根の範囲 ※必要に応じて変更のこと
!演算関連
SUB SqSet(n, a()) !a=SQR(n)とする
IF INT(n)<>n THEN
PRINT "整数を設定してください。"; n
STOP
END IF
MAT a=ZER
CALL SqNormalize(ABS(n), p,q)
IF n<0 THEN LET q=-q
LET a(q)=p
END SUB
SUB SqSetQ(x,y, a()) !a=SQR(x/y)、x:整数、y:正の整数 とする
IF y<=0 OR INT(y)<>y THEN
PRINT "正の整数を設定してください。"; y
STOP
END IF
CALL SqSet(x*y, a)
CALL SqDivN(a,y, a)
END SUB
SUB SqSetN(n, a()) !a=nとする
MAT a=ZER
LET a(1)=n
END SUB
SUB SqAdd(a(),b(), c()) !加算 c=a+b
MAT c=a+b
END SUB
SUB SqSub(a(),b(), c()) !減算 c=a-b
MAT c=a-b
END SUB
SUB SqMulN(a(),N, c()) !乗算 c=a*N ※{√(x)+√(y)+ … }*N
MAT c=(N)*a
END SUB
SUB SqDivN(a(),N, c()) !除算 c=a/N ※{√(x)+√(y)+ … }/N
IF N=0 THEN
PRINT "0では割れません。"
STOP
END IF
MAT c=(1/N)*a
END SUB
DIM w(-szRt TO szRt) !作業用
SUB SqMulS(a(),B, c()) !乗算 c=a*B ※{√(x)+√(y)+ … }*√(B)
MAT w=ZER
FOR i=LBOUND(a) TO UBOUND(a)
IF a(i)<>0 THEN !係数が0以外なら
IF i*B<0 THEN
CALL SqNormalize(ABS(i*B), p,q) !※√(-a)*√(b)=√(-a*b)、√(a)*√(-b)=√(-a*b)
LET q=-q
ELSE
CALL SqNormalize(i*B, p,q) !※√(a)*√(b)=√(a*b)
IF B<0 THEN LET p=-p !※√(-a)*√(-b)=-√(a*b)
END IF
LET w(q)=w(q)+a(i)*p !√(a[])*√(B)
END IF
NEXT i
MAT c=w
END SUB
SUB SqDivS(a(),B, c()) !除算 c=a/B ※{√(x)+√(y)+ … }/√(B)
IF B=0 THEN
PRINT "0では割れません。"
STOP
END IF
CALL SqMulS(a,B, c) !√(i)*√(B)/B ※分母を有理化する
CALL SqDivN(c,B, c)
END SUB
DIM w0(-szRt TO szRt),w1(-szRt TO szRt) !作業用
SUB SqMul(a(),b(), c()) !乗算 c=a*b ※{√(x)+√(y)+ … }*{√(u)+√(v)+ … }
MAT w0=ZER
FOR k=LBOUND(b) TO UBOUND(b)
LET Bk=b(k) !√(a[])*√(b[k])
IF Bk<>0 THEN !係数が0以外なら
CALL SqMulS(a,k, w1) !平方根の中の部分
CALL SqMulN(w1,Bk, w1) !係数の部分
MAT w0=w0+w1
END IF
NEXT k
MAT c=w0
END SUB
DIM w2(-szRt TO szRt),w3(-szRt TO szRt),w4(-szRt TO szRt),w5(-szRt TO szRt) !作業用
SUB SqDiv(a(),b(), c()) !除算 c=a/b ※{√(x)+√(y)+ … }/{√(u)+√(v)+ … }
MAT w2=a
MAT w3=b
DO
FOR k=LBOUND(b) TO UBOUND(b) !平方根を探す
IF k<>1 AND w3(k)<>0 THEN EXIT FOR
NEXT k
IF k>UBOUND(b) THEN EXIT DO !平方根がなくなれば、有理化を終了する
MAT w4=w3 !{√(u)+√(v)+ … }-√(k)をつくって、(s+t)*(s-t)=s^2-t^2の形へ
LET w4(k)=-w3(k)
CALL SqMul(w2,w4, w5) !分子側 {√(x)+√(y)+ … }*{√(u)+√(v)+ … -√(k)}
MAT w2=w5
CALL SqMul(w3,w4, w5) !分母側 {{√(u)+√(v)+ … }+√(k)}*{{√(u)+√(v)+ … }-√(k)}
MAT w3=w5
LOOP
CALL SqDivN(w2,w3(1), c) !分子/分母
END SUB
SUB SqPow(a(),n, x()) !べき乗 x=a^n ※{√(x)+√(y)+ … }^n
IF INT(n)<>n THEN
PRINT "べき乗数が整数ではありません。"; n
STOP
END IF
CALL SqSetN(1, w3) !x=1
MAT w2=a !b=a
LET n2=ABS(n)
DO UNTIL n2=0
IF MOD(n2,2)=1 THEN CALL SqMul(w3,w2, w3) !x=x*b
CALL SqMul(w2,w2, w2) !b=b*b
LET n2=INT(n2/2)
LOOP
IF n<0 THEN !負なら逆数にする
CALL SqSetN(1, w2)
CALL SqDiv(w2,w3, w3) !x=1/x
END IF
MAT x=w3
END SUB
SUB SqNormalize(n, p,q) !平方根の中をできるだけ小さな正の整数に直す
!※n=p^2*q、n,p,q≧0とすると、SQR(n)=p*SQR(q)と変形できる。
LET q=1 !※SQR(0)=0*SQR(1)とする ※n=0なら、1行下のFOR文でp=0は設定される
FOR p=INT(SQR(n)) TO 1 STEP -1 !約数p^2の候補を大きい方から
!FOR p=INTSQR(n) TO 1 STEP -1 !約数p^2の候補を大きい方から ※有理数モードのとき
LET q=n/p^2
IF q=INT(q) THEN EXIT FOR !qは自然数より
NEXT p
END SUB
!出力関連
SUB SqPrint(a()) !√(x)+√(y)+ … 形式で表示する
LET flg=0
FOR i=LBOUND(a) TO UBOUND(a) !小さい順に
LET Ai=a(i) !係数
IF Ai<>0 THEN
IF flg=1 THEN PRINT " + "; !継続なら
IF Ai<0 THEN
PRINT "( ";Ai;") ";
ELSE
IF i=1 OR Ai<>1 THEN PRINT Ai; !係数が1以外なら
END IF
IF i<>1 THEN !SQR(1)以外なら
IF Ai<>1 THEN PRINT "* "; !係数が1以外なら
PRINT "SQR(";i;")";
END IF
LET flg=1
END IF
NEXT i
IF flg=0 THEN PRINT " 0";
PRINT
END SUB
!------------------------------ ここまでがサブルーチン
DIM T1(-szRt TO szRt),T2(-szRt TO szRt),T3(-szRt TO szRt) !作業用
!●例1 SQR(32)-SQR(3)*{2*SQR(2)+SQR(6)}+12/SQR(6) の計算
DIM c2(-szRt TO szRt),c3(-szRt TO szRt),c6(-szRt TO szRt),c32(-szRt TO szRt) !定数
CALL SqSet(32, c32) !c32=SQR(32)
CALL SqSet(3, c3) !c3=SQR(3)
CALL SqSet(2, c2) !c2=SQR(2)
CALL SqSet(6, c6) !c6=SQR(6)
CALL SqMulN(c2,2, T1) !T1=2*SQR(2)
CALL SqAdd(T1,c6, T1) !T1=2*SQR(2)+SQR(6)
!CALL SqPrint(T1)
CALL SqMul(c3,T1, T3) !T3=SQR(3)*{2*SQR(2)+SQR(6)}
!!!または、CALL SqMulS(T1,3, T3) !T3=SQR(3)*{2*SQR(2)+SQR(6)}
!CALL SqPrint(T3)
CALL SqSub(c32,T3, T1) !T1=SQR(32)-SQR(3)*{2*SQR(2)+SQR(6)}
DIM n12(-szRt TO szRt) !定数
CALL SqSetN(12, n12) !n12=12
CALL SqDivS(n12,6, T2) !T2=12/SQR(6)
!CALL SqPrint(T2)
CALL SqAdd(T1,T2, T1) !T1=SQR(32)-SQR(3)*{2*SQR(2)+SQR(6)}+12/SQR(6)
CALL SqPrint(T1) !結果
!●例2 (-5+SQR(-9))/(3-SQR(-4)) の計算
DIM n3(-szRt TO szRt),nm5(-szRt TO szRt) !定数
CALL SqSetN(3, n3) !n3=3
CALL SqSetN(-5, nm5) !nm5=-5
DIM cm4(-szRt TO szRt),cm9(-szRt TO szRt) !定数
CALL SqSet(-4, cm4) !cm4=SQR(-4)
CALL SqSet(-9, cm9) !cm9=SQR(-9)
CALL SqAdd(nm5,cm9, T1) !T1=-5+SQR(-9)
CALL SqSub(n3,cm4, T2) !T2=3-SQR(-4)
CALL SqDiv(T1,T2, T3) !T3=(-5+SQR(-9))/(3-SQR(-4))
CALL SqPrint(T3) !結果
END
> SET WINDOW -500,500,-500,500
> LET phi=(1+SQR(5))/2 !黄金比
> LET a=2*PI*phi !黄金角
> LET r=1
> LET th=0
> FOR i=0 TO 900
> LET r=1.1*r !らせん状
> LET th=th+a
> LET x1=r*COS(th)
> LET y1=r*SIN(th)
> !DRAW disk WITH SCALE(r*0.3)*SHIFT(x1,y1)
> DRAW circle WITH SCALE(r*0.3)*SHIFT(x1,y1)
> NEXT i
> END
> Meの場合、OSのDIBENG.DLLでエラーとなりBASICが強制終了となる。
SET WINDOW -5,5,-5,5
DRAW grid2(0,1)
END
EXTERNAL PICTURE grid2(p,q)
ASK WINDOW x1,x2,y1,y2
IF p<>0 THEN LET a=p ELSE LET a=2*(ABS(x1)+ABS(x2))
IF q<>0 THEN LET b=q ELSE LET b=2*(ABS(y1)+ABS(y2))
DRAW GRID(a,b)
END PICTURE
SUB Dxyzn( kx,ky,kz,kn, x,y,z,n)
LET kx= I(t)-120*y^3*z*(x-115) -40*n^4*(x+12) -.24*(x-10.613) ! (d V/dt)
LET ky= .1*(25-x)/(EXP((25-x)/10)-1)*(1-y) -4*EXP(-x/18)*y ! (d m/dt)
LET kz= .07*EXP(-x/20)*(1-z)
-1/(EXP((30-x)/10)+1)*z !
(d h/dt)
LET kn= .01*(10-x)/(EXP((10-x)/10)-1)*(1-n) -.125*EXP(-x/80)*n! (d n/dt)
END SUB
LET I0=20 !膜電流 パラメーター
LET A=40
LET f=.3000001
!
LET x=6.24 !初期値 x,y,z,n
LET y=.0761
LET z=.301
LET n=.519
LET dt=.05 !RungeKutta pitch time
LET t99=500 !RungeKutta close time
DATA -15,100, -.3,1, -.04,.45 !座標軸の両端座標 xL,xH, yL,yH, zL,zH
MAT READ LH
LET zox=35 !回転 旋回中心点 center へのオフセットxyz
LET zoy=.6
LET zoz=.2
!
LET Sx=1 !スケール倍率 Sx,Sy,Sz
LET Sy=50
LET Sz=200
LET xm=35 !画面中心 xm,ym
LET ym=35
LET hw=80 !画面幅/2 ±hw
!
LET ax=-75 !z軸をx軸で倒す開始角度
LET ay=0 !z軸をy軸で倒す開始角度
LET SS=0 !z軸 回転開始角度
LET ST= +5 !z軸 回転ステップ +:左回転 -:右回転
!
SET WINDOW xm-hw,xm+hw,ym-hw,ym+hw
CALL graph3D
!-----
SUB RungeKutta
CALL Dxyzn( kx1,ky1,kz1,kn1, x,y,z,n)
CALL Dxyzn( kx2,ky2,kz2,kn2, x+kx1*dt/2,y+ky1*dt/2,z+kz1*dt/2,n+kn1*dt/2)
CALL Dxyzn( kx3,ky3,kz3,kn3, x+kx2*dt/2,y+ky2*dt/2,z+kz2*dt/2,n+kn2*dt/2)
CALL Dxyzn( kx4,ky4,kz4,kn4, x+kx3*dt ,y+ky3*dt ,z+kz3*dt ,n+kn3*dt )
LET x=x+(kx1+2*kx2+2*kx3+kx4)*dt/6
LET y=y+(ky1+2*ky2+2*ky3+ky4)*dt/6
LET z=z+(kz1+2*kz2+2*kz3+kz4)*dt/6
LET n=n+(kn1+2*kn2+2*kn3+kn4)*dt/6
END SUB
SUB graph3D
! 回転 旋回中心点 center を 原点へ移動し、又、元へ戻す行列。
!(x,y,z,1)| 1, 0, 0,
0 |
!
| 0, 1, 0,
0 |
!
| 0, 0, 1,
0 |
! |-zox*Sx,-zoy*Sy,-zoz*Sz, 1 |
LET shxyzM(4,1)=-zox*Sx
LET shxyzM(4,2)=-zoy*Sy
LET shxyzM(4,3)=-zoz*Sz
!
!(x,y,z,1)| 1, 0, 0,
0 |
!
| 0, 1, 0,
0 |
!
| 0, 0, 1,
0 |
! | zox*Sx, zoy*Sy, zoz*Sz, 1 |
LET shxyzP(4,1)=zox*Sx
LET shxyzP(4,2)=zoy*Sy
LET shxyzP(4,3)=zoz*Sz
!
LET az=SS
CALL rot_panel
!---3D 曲線、1回目で、3D原画 記録を撮る。
LET ci=0
FOR t=0 TO t99 STEP dt
LET copy(ci,1)=x
LET copy(ci,2)=y
LET copy(ci,3)=z
! PRINT x;y;z;n ! データーを保存したい時。
CALL line3D(x,y,z)
CALL RungeKutta
LET ci=ci+1
NEXT t
!----
MOUSE POLL m_x,m_y,mlb,mrb
LET mxbak=m_x
LET mybak=m_y
DO
IF mlb=0 THEN LET az=MOD(az+ST,360) ! z軸で、1ステップ回す。
SET DRAW mode hidden
CALL rot_panel
!---3D 曲線、2回目以降は、記録の再生で、高速描画。
FOR ci=0 TO ci-1
CALL line3D( copy(ci,1),copy(ci,2),copy(ci,3) )
NEXT ci
SET DRAW mode explicit
!----
MOUSE POLL m_x,m_y,mlb,mrb
IF mlb=1 THEN
LET ax=ax -(m_y-mybak)!/2 ! 変移方向は、+90度 回す。
LET ay=ay +(m_x-mxbak)!/2
END IF
LET mxbak=m_x
LET mybak=m_y
! WAIT DELAY 0.05
LOOP UNTIL mrb=1
END SUB
SUB rot_panel
LET ar0=SQR(ax^2+ay^2) ! 旋回角度
IF ar0<>0 THEN LET DIRar0=ANGLE(ax,ay) ! 旋回軸の方向
IF 180< ar0 THEN
LET ax=(ar0-360)*COS(DIRar0)
LET ay=(ar0-360)*SIN(DIRar0)
END IF
! xy平面上、0度方向(x軸)を、軸として旋回する行列 rotx
!(x,y,z,1)|
1, 0, 0,
0 |
! | 0, cos(ar0), sin(ar0), 0 |
! | 0,-sin(ar0), cos(ar0), 0 |
! |
0, 0, 0,
1 |
LET rotx(2,2)=COS(ar0)
LET rotx(3,2)=-SIN(ar0)
LET rotx(2,3)=SIN(ar0)
LET rotx(3,3)=COS(ar0)
!
MAT P3D= shxyzM*ROTATE(az-DIRar0)*rotx*ROTATE(DIRar0)*shxyzP !変形指示MAT
!----
CLEAR
PLOT TEXT,AT xm-hw*.9,ym+hw*.90 :t2$
PLOT TEXT,AT xm-hw*.9,ym+hw*.83 :t$
PLOT TEXT,AT xm+hw*.1,ym+hw*.83,USING"Ax=#### Ay=#### Az=####":ax,ay,az
PLOT TEXT,AT xm-hw*.9,ym-hw*.92 :t5$
PLOT TEXT,AT xm-hw*.9,ym-hw*.99 :t4$& " "& t3$ ! PEN-off
!---
IF ar0< 90 THEN SET AREA COLOR "cyan" ELSE SET AREA COLOR "black"
DRAW disk WITH SCALE(15)*P3D ! 原点近傍、裏表 のマーカー1
DRAW disk WITH SCALE(5)*SHIFT(zox*Sx,zoy*Sy)*P3D ! マーカー2
CALL axes3D( zox,zoy,0, zox,zoy,zoz, "center" ) ! マーカー3
!---座標軸
CALL axes3D( LH(1),0,0, LH(2),0,0, STR$(LH(2))& "( X)" )
CALL axes3D( 0,LH(3),0, 0,LH(4),0, STR$(LH(4))& "( Y)" )
CALL axes3D( 0,0,LH(5), 0,0,LH(6), STR$(LH(6))& "( Z)" )
END SUB
SUB axes3D(x1,y1,z1, x2,y2,z2, a$ )
CALL line3D(x1,y1,z1)
CALL line3D(x2,y2,z2)
PLOT TEXT,AT pV(1),pV(2) :a$ ! PEN-off
END SUB
SUB line3D(x,y,z)
LET pV(1)=x*Sx !描画目盛は、全方向等しくないと、回転で、形が保てない。
LET pV(2)=y*Sy !スケール Sx,Sy,Sz の違いは、入力の倍率として、行なう。
LET pV(3)=z*Sz !入力 z 座標は 出力 x,y に反映。出力zは 描画不可。
LET pV(4)=1 ! shxyzM …shxyzP で必要。
MAT pV=pV*P3D
PLOT LINES: pV(1),pV(2); ! PEN-on
END SUB
!対数の計算
!自然数nを、素因数分解 n=2^a*3^b*5^c* … とすると、
!LOG(n)=LOG(2^a*3^b*5^c* … )=a*LOG(2)+b*LOG(3)+c*LOG(5)+ … となる。
!真数が同じ素数のものを同類項としてまとめることができる。
OPTION ARITHMETIC RATIONAL
LET szLg=100 !扱う対数の範囲 ※必要に応じて変更のこと
LET cBASE=2 !仮の底 ※正の実数 a≠1 をとる
!演算関連
SUB LogSet(n, a()) !a=LOG(n)とする
IF n<=0 OR INT(n)<>n THEN
PRINT "非負の整数ではありません。"; n
STOP
END IF
MAT a=ZER
LET x=n !素因数分解 n=2^a*3^b*5^c* …
LET m=2
DO WHILE x>1 !1まで繰り返す
LET K=0
DO WHILE MOD(x,m)=0 !mで割り切れるなら(mは因数)
LET x=x/m !割り切れるまで(m^Kの形)
LET K=K+1
LOOP
LET a(m)=K !m^K ※ … + K*LOG(m) + …
IF m>2 THEN !2,3,5,7,9,・・・で調べる
LET m=m+2
ELSE
LET m=m+1
END if
LOOP
END SUB
DIM w0(szLg),w1(szLg) !作業用
SUB LogSetQ(x,y, a()) !a=LOG(x/y)、x:整数、y:正の整数 とする
IF y<=0 OR INT(y)<>y THEN
PRINT "正の整数を設定してください。"; y
STOP
END IF
CALL LogSet(x, w0) !LOG(x/y)=LOG(x)-LOG(y)
CALL LogSet(y, w1)
CALL LogSub(w0,w1, a)
END SUB
SUB LogSetN(n, a()) !a=nとする
MAT a=ZER
LET a(cBASE)=n
END SUB
SUB LogAdd(a(),b(), c()) !加算 c=a+b
MAT c=a+b
END SUB
SUB LogSub(a(),b(), c()) !減算 c=a-b
MAT c=a-b
END SUB
SUB LogMulN(a(),N, c()) !乗算 c=a*N ※{Log(x)+Log(y)+ … }*N
MAT c=(N)*a
END SUB
SUB LogDivN(a(),N, c()) !除算 c=a/N ※{Log(x)+Log(y)+ … }*N
IF N=0 THEN
PRINT "0では割れません。"
STOP
END IF
MAT c=(1/N)*a
END SUB
!出力関連
SUB LogPrint(a()) !LOG(x)+LOG(y)+ … 形式で表示する
LET flg=0
FOR i=1 TO UBOUND(a) !小さい順に
LET Ai=a(i) !係数
IF Ai<>0 THEN
IF flg=1 THEN PRINT " + "; !継続なら
IF Ai<0 THEN
PRINT "( ";Ai;") ";
ELSE
IF i=cBASE OR Ai<>1 THEN PRINT Ai; !係数が1以外なら
END IF
IF i<>cBASE THEN !真数が底以外なら
IF Ai<>1 THEN PRINT "* "; !係数が1以外なら
PRINT "Log";STR$(cBASE);"(";i;")";
END IF
LET flg=1
END IF
NEXT i
IF flg=0 THEN PRINT " 0";
PRINT
END SUB
SUB LogPrintQ(a()) !m/n+LOG(x/y) 形式で表示する
CALL LogPack(a, K,x1,x2)
IF K<>0 THEN PRINT K; !有理数の部分
!無理数の部分
IF x1/x2=1 THEN !真数=1の場合
IF K=0 THEN PRINT "+ 0";
ELSEIF x1=1 THEN !真数=1/x2の場合
PRINT "- Log";STR$(cBASE);"(";x2;")";
ELSE
PRINT "+ Log";STR$(cBASE);"(";x1/x2;")";
END IF
PRINT
END SUB
!補助ルーチン
DIM b(szLg),c(szLg) !作業用
SUB LogYYY(a(),b(), K) !c=a-b^Kを調べる
LET K=0 !引いた回数
FOR i=1 TO UBOUND(b)
IF b(i)<>0 THEN EXIT FOR !最小の素因数を探す
NEXT i
IF i>UBOUND(a) OR a(i)=0 THEN EXIT SUB !共通な素因数がない場合
LET cSGN=1 !符号
IF a(i)*b(i)<0 THEN LET cSGN=-1
MAT c=a
DO
IF cSGN>0 THEN MAT c=c-b ELSE MAT c=c+b
FOR i=1 TO UBOUND(c)
IF c(i)*a(i)<0 THEN EXIT DO !引きすぎかどうか確認する
NEXT i
LET K=K+1
LOOP
LET K=cSGN*K
IF cSGN>0 THEN MAT c=c+b ELSE MAT c=c-b !引き戻し
END SUB
SUB LogPack(a(), K,nn,mm) !1つの項にまとめる a*Log(x)+b*Log(y)+ … =Log(x^a*y^b* … )
IF INT(cBASE)=cBASE THEN !整数なら
CALL LogSet(cBASE, b) !底を素因数分解する
ELSE
CALL LogSetQ(NUMER(cBASE),DENOM(cBASE), b)
END IF
CALL LogYYY(a,b, K) !真数=底^K ?
IF K=0 THEN
CALL LogYYY(b,a, K) !底と真数をひっくり返す。底=真数^K ?
IF k<>0 THEN LET K=1/K
END IF
IF K<>0 THEN MAT a=c
LET nn=1 !分子
LET mm=1 !分母
FOR i=1 TO UBOUND(a) !真数を1つにまとめる
IF a(i)<0 THEN !係数が負なら、分母へ
LET mm=mm*i^ABS(a(i))
ELSE
LET nn=nn*i^a(i)
END IF
NEXT i
IF nn<>1 AND mm=1 THEN !真数が1より大きな整数なら
FOR i=1 TO UBOUND(b) !底
IF b(i)<>0 THEN
IF a(i)=0 THEN !共通素因子がなければ
LET K1=0
EXIT FOR
END IF
LET K1=a(i)/b(i) !底=真数^K1 ?
END IF
NEXT i
IF K1<>0 THEN
LET K=K+K1
LET nn=1
END IF
END IF
!!!PRINT "K=";K; "nn=";nn; "mm=";mm !debug
END SUB
!------------------------------ ここまでがサブルーチン
DIM T1(szLg),T2(szLg),T3(szLg),T4(szLg) !作業用
!●例1 LOG(2/3)+LOG(12/25)-LOG(8/15) = LOG(3)-LOG(5) = LOG(3/5) の計算
LET cBASE=2 !底
CALL LogSetQ(2,3, T1) !T1=LOG(2/3)
CALL LogSetQ(12,25, T2) !T1=LOG(12/25)
CALL LogAdd(T1,T2, T1)
CALL LogSetQ(8,15, T2) !T1=LOG(8/15)
CALL LogSub(T1,T2, T1)
!!!MAT PRINT T1; !debug
CALL LogPrint(T1)
CALL LogPrintQ(T1)
!●例2 LOG10(7/4)-LOG10(9)-2*LOG10(5/3)-LOG10(49)/2 = -2 の計算
LET cBASE=10 !底
CALL LogSetQ(7,4, T1) !T1=LOG(7/4)
CALL LogSet(9, T2) !T2=LOG(9)
CALL LogSub(T1,T2, T1)
CALL LogSetQ(5,3, T2) !T2=LOG(5/3)
CALL LogMulN(T2,2, T2)
CALL LogSub(T1,T2, T1)
CALL LogSet(49, T2) !T2=LOG(49)
CALL LogDivN(T2,2, T2)
CALL LogSub(T1,T2, T1)
!MAT PRINT T1; !debug
CALL LogPrint(T1)
CALL LogPrintQ(T1)
!●例3 LOG27(1/9) = -2/3 の計算
!LET cBASE=9
LET cBASE=27
!CALL LogSetQ(1,3, T1)
CALL LogSetQ(1,9, T1)
!MAT PRINT T1; !debug
CALL LogPrint(T1)
CALL LogPrintQ(T1)
END
OPTION ARITHMETIC RATIONAL
LET MaxLevel=200 !循環節の最大桁数
DIM s(MaxLevel) !循環節の候補
!●循環小数を分数へ
!筆算
! x=0.1[23]
! 100*x-x=12.3[23]-0.1[23]=12.2 ∴99*x=122/10 ∴x=61/495
!LET x$="2.2[234]" !2.2234234234…
!LET x$="0.0[90]" !0.0909090…
!LET x$="0.[142857]" !0.142857142857…
LET x$="0.1[23]" !0.1232323…
PRINT ExVAL(x$)
!● 0.1[23] ÷ 0.[14] の結果を循環小数で表せ。 答え 0.8[714285]
LET t=ExVAL("0.1[23]") / ExVAL("0.[14]")
PRINT t, ExSTR$(t)
FUNCTION ExVAL(x$) !数値を表現する文字列を数値に変換する
LET L=LEN(x$) !文字列長を得る
LET p=0 !有限小数の桁数
LET k=0 !循環節の桁数。有限小数の場合、0
LET A=0
LET cSGN=1 !符号
LET flag=0 !「整数」 ※数値の型
LET i=1 !数字列の読み込み位置
DO WHILE i<=L !上位の桁から順に
LET t$=UCASE$(x$(i:i))
IF t$="." THEN !小数点なら
IF flag<>0 THEN
PRINT "小数点の位置が不正です。"; x$
STOP
END IF
LET flag=1 !「有限小数」
ELSEIF t$="+" THEN !+符号なら
IF i<>1 THEN
PRINT "+符号の位置が不正です。"; x$
STOP
END IF
ELSEIF t$="-" THEN !−符号なら
IF i<>1 THEN
PRINT "−符号の位置が不正です。"; x$
STOP
END IF
LET cSGN=-1
ELSEIF t$="[" THEN !循環小数なら
IF flag<>1 THEN !小数部か?
PRINT "循環小数の開始位置が不正です。"; x$
STOP
END IF
LET flag=2 !「循環小数」
ELSEIF t$="]" THEN
IF i<>L THEN !右端か?
PRINT "循環小数の終了位置が不正です。"; x$
STOP
END IF
ELSE
LET A=A*10+VAL(t$) !多項式(( … ((a[1]*10+a[2])*10+a[3])*10 … +a[i-2])*10+a[i-1])*10+a[i] ※左シフト
IF flag=1 THEN LET p=p+1
IF flag=2 THEN LET k=k+1
END IF
LET i=i+1 !次へ
LOOP
!PRINT A; flag;cSGN;p;k !debug
IF flag<2 THEN !有限小数(整数も含む)の場合
LET ExVAL=cSGN * A/10^p
ELSE !循環小数の場合
LET B=INT(A/10^k)
LET ExVAL=cSGN * (A-B)/(10^(k+p)-10^p)
END IF
END FUNCTION
FUNCTION ExSTR$(x) !数値式を表示するときの文字列に変換する
LET a=ABS(x)
!整数部
LET aa=INT(a) !小数部を削除する
LET b$="" !変換後の数
DO WHILE aa>=10
LET b$=STR$(MOD(aa,10))&b$ !a=b[k]*10^k+b[k-1]*10^(k-1)+ … +b[1]*10^1+b[0]*10^0より
LET aa=INT(aa/10) !次の桁へ ※右シフト
LOOP
LET b$=STR$(aa)&b$
!小数部
LET aa=a-INT(a) !整数部を削除する
LET k=1 !小数桁
DO UNTIL aa=0 !小数第1位から順に
IF k=1 THEN !初回のみ
LET b$=b$&"." !小数点をつける
LET p=POS(b$,".")
ELSE
FOR i=1 TO k-1 !循環したか確認する
IF s(i)=aa THEN !循環節
LET b$(i+p:i+p)="["&b$(i+p:i+p) !開始記号を挿入
LET b$=b$&"]" !終了記号
EXIT DO
END IF
NEXT i
END IF
LET s(k)=aa
LET aa=aa*10 !左シフト
LET b$=b$&STR$(INT(aa)) !a=S[-1]*10^(-1)+S[-2]*10^(-2)+ … +S[-(k-1)]*10^(-(k-1))+S[-k]*10^(-k)より
LET aa=aa-INT(aa) !整数部分を削除して、次の桁へ
LET k=k+1
IF k>MaxLevel THEN !循環小数によるループを回避する
PRINT "変換を打ち切りました。"
EXIT DO
END IF
LOOP
IF x<0 THEN LET ExSTR$="-"&b$ ELSE LET ExSTR$=b$ !….…形式
END FUNCTION
END
<システムのプロパティ> のコピー。
全般 <仮想メモリ>
システム : ハードディスク: C:\4417MB の空き
Microsoft Windows 98 最小: 128 MB
Second
Edition
最大: 最大値なし
4.10.2222 A
製造およびサポート元 :
NEC
LaVie
GenuineIntel
x86 Family 6 Model 8 Stepping 1
255.0MB の RAM
FOR u= left TO right STEP (right-left)/px
FOR v = bottom TO top STEP (top-bottom)/py
LET Lambda=COMPLEX(u,v)
LET z=0.5 ! 初期値
FOR n = 1 TO 250
IF ABS(i*z)< 710 THEN LET z=lambda*sin(z) ELSE EXIT FOR !桁あふれ防止
NEXT n
IF 250< n THEN PLOT POINTS: u,v
NEXT v
NEXT u
山中和義さんの FUNCTION ExSTR$(x) で分数を循環小数に変換するループを拝見し、これを10進15桁モードではできないかと思い立ち作ってみました。
計算過程は筆算と同じです。分母をnとすれば、n-1桁までで割り切れるか同じ余りが現れるかです。
計算結果の桁数に制限はないのです(真値が求まります)が、分母の大きさで配列sを宣言しているため、分母が大きすぎるとエラーになります。
1000桁モード,有理数モードでも実行できます。(2進モードでは小数で誤差が出てしまう)
DECLARE EXTERNAL FUNCTION Ex2STR$ ! 分数を小数,循環小数の文字列に変換する関数
DO
READ IF MISSING THEN EXIT DO : x$
PRINT x$ ; " 入力数値"
CALL fraction(x$,a,b) ! 整数,有限小数,循環小数,分数の文字列(x$)を既約分数(a/b)に変換
IF a>=0 THEN LET m$=" " ELSE LET m$=""
IF b=1 THEN LET f$=STR$(a) ELSE LET f$=STR$(a)&"/"&STR$(b)
PRINT m$&f$ ; " 分数表示"
PRINT a/b ; " 小数15桁表示"
PRINT m$&Ex2STR$(a,b) ; " 小数真値[循環節]表示" ! 分数(a/b)を小数,循環小数の文字列に変換
PRINT
LOOP
DATA "-18" , "47." , "-12.34" , "-.67" , "+972.[51]" , "-73.482[3058]"
DATA "0.000[217]" , "+6.0054[83]" , ".031[040]" , "-78/13" , "0/26" , "740.52/29.84"
DATA "634517/3637" , "24/56" , "-5/12" , "91/35" , "886240513930735/10485760"
END
EXTERNAL SUB fraction(x$,numer,denom) ! x$を分数numer/denomに変換
LET dec$=LTRIM$(RTRIM$(x$))
IF dec$(1:1)="-" THEN LET s=-1 ELSE LET s=1
IF dec$(1:1)="+" OR dec$(1:1)="-" THEN LET dec$=dec$(2:LEN(dec$))
LET sp=POS(dec$,"/")
IF sp>1 THEN ! 分数
LET numer=VAL(dec$(1:sp-1))
LET denom=VAL(dec$(sp+1:LEN(dec$)))
CALL reduce(numer,denom) ! 約分
LET numer=s*numer
EXIT SUB
END IF
LET dp=POS(dec$,".")
IF dp=0 OR dp=LEN(dec$) THEN ! 整数
LET numer=s*VAL(dec$)
LET denom=1
EXIT SUB
END IF
IF dp=1 THEN LET intp=0 ELSE LET intp=VAL(dec$(1:dp-1)) ! 整数部
LET rp=POS(dec$,"[")
IF rp=0 THEN ! 有限小数
LET dl=LEN(dec$)-dp
LET denom=10^dl
LET numer=intp*denom+VAL(dec$(dp+1:LEN(dec$)))
CALL reduce(numer,denom)
LET numer=s*numer
EXIT SUB
END IF
IF rp=dp+1 THEN
LET dconst=0 ! 例"37.[61]"
LET dconst_denom=1
LET dl=0
ELSE
LET dconst=VAL(dec$(dp+1:rp-1)) ! 小数定数部
LET dl=rp-dp-1 ! 小数定数部桁数
LET dconst_denom=10^dl
CALL reduce(dconst,dconst_denom)
END IF
LET rl=LEN(dec$)-rp-1 ! 循環節桁数
LET recur=VAL(dec$(rp+1:LEN(dec$)-1)) ! 循環節
LET recur_denom=10^(LEN(dec$)-dp-2)*(1-1/10^rl)
CALL reduce(recur,recur_denom)
!PRINT intp;dconst;dconst_denom;intp+dconst/dconst_denom
!PRINT recur;recur_denom;recur/recur_denom
!! intp/1 + dconst/dconst_denom + recur/recur_denom
LET numer=intp*dconst_denom+dconst
CALL reduce(numer,dconst_denom)
LET numer=numer*recur_denom+recur*dconst_denom
LET denom=dconst_denom*recur_denom
CALL reduce(numer,denom)
LET numer=s*numer
END SUB
EXTERNAL FUNCTION Ex2STR$(numer,denom) !分数を小数,循環小数の文字列に変換
!「No.422 循環小数の計算(山中和義氏)」FUNCTION ExSTR$(x) 参照
IF SGN(numer/denom)=-1 THEN LET u$="-" ELSE LET u$=""
LET numer=ABS(numer)
LET denom=ABS(denom)
CALL reduce(numer,denom) ! 約分
!整数部
IF denom=1 THEN
LET Ex2STR$=u$&STR$(numer)
EXIT FUNCTION
END IF
DIM s(denom-1) ! 剰余を格納する配列
LET aa=INT(numer/denom) !小数部を削除する
IF aa=0 THEN LET b$="." ELSE LET b$=STR$(aa)&"."
!小数部
LET p=POS(b$,".")
LET numer=MOD(numer,denom) ! 剰余(商=aa)
LET k=1 !小数桁
DO UNTIL numer=0
FOR i=1 TO k-1 !循環したか確認する
IF s(i)=numer THEN
LET b$(i+p:i+p)="["&b$(i+p:i+p) !開始記号を挿入
LET b$=b$&"]" !終了記号
EXIT DO
END IF
NEXT i
LET s(k)=numer
LET b$=b$&STR$(INT(10*numer/denom))
LET numer=MOD(10*numer,denom)
LET k=k+1
IF k>denom THEN ! 配列sの添字オーバーを回避する
PRINT "変換を打ち切りました。"
EXIT DO
END IF
LOOP
LET Ex2STR$=u$&b$
END FUNCTION
EXTERNAL SUB reduce(p,q) ! 約分
!十進BASIC添付 "\BASICw32\Math\GCDLOOP.BAS" 参照
REM 互除法により,入力された2数の最大公約数を求める → その後,約分
LET a=p
LET b=q
DO
LET r=MOD(a,b)
IF r=0 THEN EXIT DO
LET a=b
LET b=r
LOOP
LET p=p/b
LET q=q/b
END SUB
OPTION ARITHMETIC NATIVE
OPTION ANGLE DEGREES
LET theta0=-125
LET z0=10
REM z軸のまわりにtheta0度回転したsphreを,
REM 点(0,0,z0)から見たように描く。
DIM p(4,4) ! 点 0,0,z0を中心とする射影
MAT p=IDN
LET p(3,4)=-1/z0
DIM rotx(4,4) ! x軸のまわりの-90°回転
MAT rotx=IDN
LET rotx(2,2)=COS(-90)
LET rotx(2,3)=SIN(-90)
LET rotx(3,2)=-SIN(-90)
LET rotx(3,3)=COS(-90)
ASK PIXEL SIZE (0,1;1,0) a,b
DIM sp(a,b)
SET COLOR mode "NATIVE"
SET WINDOW -2, 2, -2, 2
DRAW sphere0 WITH ROTATE(theta0) * rotx
ASK PIXEL ARRAY (-2,2) sp
FOR t = 0 TO 360*3 STEP 15 ! 球体を3回バウンドさせる
SET DRAW mode hidden
CLEAR
DRAW sphere WITH SHIFT(0,SIN(t))
SET DRAW mode explicit
NEXT t
PICTURE sphere
MAT PLOT CELLS ,IN -2,2; 2,-2: sp
END PICTURE
DIM sz(4,4),ry(4,4)
MAT READ sz
DATA 1,0,0,0
DATA 0,1,0,0
DATA 0,0,1,0
DATA 0,0,1,1
MAT READ ry
DATA 0, 0,-1, 0
DATA 0, 1, 0, 0
DATA 1, 0, 0, 0
DATA 0, 0, 0, 1
! 球面を描く
SET AREA STYLE "SOLID"
FOR t=0 TO 180
FOR p=0 TO 359
LET ry(1,3)=-SIN(t)
LET ry(3,1)=SIN(t)
LET ry(1,1)=COS(t)
LET ry(3,3)=COS(t)
DRAW Trapezoid(t) WITH sz*ry*ROTATE(p)
NEXT p
NEXT t
PICTURE Trapezoid(t) ! tは天頂角
DIM N(3)
CALL makeNormal(N)
IF N(3)>0 THEN ! 外側が手前なら面を描く
CALL setBrightness(N)
PLOT AREA: -PI/360,
-SIN(t-0.5)*PI/360; PI/360,-SIN(t+0.5)*PI/360;
PI/360,SIN(t+0.5)*PI/360; -PI/360,SIN(t-0.5)*PI/360
END IF
END PICTURE
END PICTURE
! 変換された座標系における法線ベクトルを求める
EXTERNAL SUB makeNormal(N())
OPTION ARITHMETIC NATIVE
DIM m(4,4),A(4),B(4),C(4)
MAT m=TRANSFORM
MAT READ A
DATA 0,0,0,1
MAT READ B
DATA 1,0,0,1
MAT READ C
DATA 1,1,0,1
MAT A=A*M
MAT B=B*M
MAT C=C*M
MAT A=(1/A(4))*A
MAT B=(1/B(4))*B
MAT C=(1/C(4))*C
MAT REDIM A(3)
MAT REDIM B(3)
MAT REDIM C(3)
MAT A=B-A
MAT B=C-B
MAT N=CROSS(A,B)
END SUB
EXTERNAL SUB setBrightness(N())
OPTION ARITHMETIC NATIVE
DIM A(3)
MAT READ A ! 光源の向き
DATA -4,5,3
LET s=DOT(A,N)/(SQR(DOT(A,A))*SQR(DOT(N,N)))
LET s=(0.8*s+1)/2
SET AREA COLOR COLORINDEX(s,s,s)
END SUB
!カラー・ボール
!-------------------------------
OPTION ARITHMETIC NATIVE
OPTION ANGLE DEGREES
DIM rotx(4,4)
MAT rotx=IDN
SET WINDOW -10,10,-10,10
! xy平面上の描点を、x軸で回転する行列 rotx
LET ar0=35
!(x,y,z,1)| 1, 0, 0, 0 |
! | 0, cos(ar0), sin(ar0), 0 |
! | 0,-sin(ar0), cos(ar0), 0 |
! |
0, 0, 0,
1 |
LET rotx(2,2)=COS(ar0)
LET rotx(3,2)=-SIN(ar0)
LET rotx(2,3)=SIN(ar0)
LET rotx(3,3)=COS(ar0)
LET r=5 ! 半径5mのカラー・ボール
LET t0=TIME
DO
LET t=TIME-t0
SET DRAW mode hidden
CLEAR
LET y=5-4.9*t^2 ! 頂点が5mの放物線
DRAW ball WITH SHIFT(0,y)
SET DRAW mode explicit
IF y< -4 THEN LET t0=t0+2*SQR((5+4)/4.9) !( 5m → -4m )時間の2倍で平行移動。
LOOP
PICTURE ball
FOR i=-r*0.9 TO r*0.9 STEP r*0.1
SET AREA COLOR MOD(i-0.6, 0.2*r)*5
DRAW disk WITH SCALE( SQR(r^2-i^2) )*rotx*SHIFT(0, SIN(ar0)*i)
NEXT i
END PICTURE
SUB SetWindowPos( handle, C2, x0,y0,xw,yw, nFLG ) ! nFLG, 0=x0y0xwyw 1=x0y0 2=xwyw
ASSIGN "user32.dll","SetWindowPos"
END SUB
!----------------------------------------------------------
SET BITMAP SIZE 501,501
LET V=5 ! 表示列数 3~5
SET WINDOW 0, V, 27,-6
SET AREA COLOR 5
DIM p$(5*V),wild$(5*V),names$(200)
!下の DATA 文は、各フォルダーが配下に見える場所(BASIC.EXE と同じ場所)に
!このプログラムを置いて起動する場合の例。
DATA TEXTFILE\, TUTORIAL\, USERLIB\, COMM\
DATA COMPLEX\, FRACTAL\, FUNCTION\, GUIDE\
DATA LIBRARY\, MATH\, MICROSFT\, "Q&A\"
DATA SAMPLE\, STATEMEN\, ".\", "C:\My Documents\*.txt"
FOR f=1 TO 25
READ IF MISSING THEN EXIT FOR: w$
FILE splitname(w$) p$(f), name$, ext$ ! ext$は語頭に"."含む。
IF ext$="" THEN LET wild$(f)="*.*" ELSE LET wild$(f)=name$& ext$
NEXT f
LET w=13 !最初に開くフォルダー、1〜?番目
CALL basfiles
OPEN #9 : TextWindow2
ERASE #9
CALL SetWindowPos( WinHandle("TEXTWINDOW2" ),0, 515, 0,509,172, 0)
PRINT #9 :"フォルダーを、選んで"
PRINT #9 :"ファイル名を、左クリックすると、内容表示する。"
PRINT #9 :"※重ねて再度、左クリックすると、(.BAS ならば、)"
PRINT #9 :" BASIC を、新しく起動、実行できます。閉じると、続行。"& CHR$(0)
DO
MOUSE POLL mx,my,mlb,mrb
IF mrb=1 THEN EXIT DO !右クリック
IF mlb=1 THEN !左クリック
IF -1< my THEN
IF 0< my THEN LET b=INT(mx)*27+CEIL(my) ELSE LET b=bak+1
IF b=< n THEN
IF b<>bak THEN
CALL sampdisp
ELSEIF UCASE$(right$(names$(b),4))=".BAS" THEN
execute "BASIC.EXE" WITH("/NR",p$(m)& names$(b))
END IF
END IF
ELSEIF my< -1 THEN
LET w=INT(my+6)*V+CEIL(mx)
IF w< f THEN CALL basfiles
END IF
LET i=0
DO
WAIT DELAY .02
MOUSE POLL mx,my,mlb,mrb
IF mlb=0 AND mrb=0 THEN LET i=i+1 ELSE LET i=0
LOOP UNTIL 5< i !マウスボタンが離れるまで待つ。
END IF
WAIT DELAY 0 !クロックアップを押える
LOOP
PLOT AREA:0,-1;V,-1;V,0;0,0
SET TEXT BACKGROUND "TRANSPARENT" ! background none
PLOT TEXT,AT V*.3,0 :"終了しました。"
SUB basfiles
LET m=w
CLEAR
PLOT AREA:0,-1;V,-1;V,0;0,0
SET TEXT BACKGROUND "TRANSPARENT" ! background none
PLOT TEXT,AT V*.17,0 :"ココを左クリックすると順送り。 右クリックで、終了。"
FOR i=0 TO 4
FOR j=1 TO V
LET w=i*V+j
IF w=m THEN PLOT AREA:j-1,i-5;j,i-5;j,i-6;j-1,i-6
IF wild$(w)="*.*" THEN LET w$=p$(w) ELSE LET w$=p$(w)& wild$(w)
PLOT TEXT,AT j-1+0.03,i-5 :w$ !p$(w)& wild$(w)
NEXT j
NEXT i
IF m>0 THEN LET n=files(p$(m)& wild$(m))
IF n>0 THEN file list p$(m)& wild$(m), names$
SET TEXT BACKGROUND "OPAQUE" ! background color 0
FOR w=1 TO n
PLOT TEXT,AT IP((w-1)/27)+0.03, MOD((w-1),27)+1 :"|"& names$(w)
NEXT w
LET bak=0
END SUB
SUB sampdisp
LET x=IP((bak-1)/27)
LET y=MOD((bak-1),27)
SET LINE COLOR 0
PLOT LINES:x,y; x+1-0.03,y; x+1-0.03,y+1; x,y+1; x,y
LET x=IP((b-1)/27)
LET y=MOD((b-1),27)
SET LINE COLOR 2
PLOT LINES:x,y; x+1-0.03,y; x+1-0.03,y+1; x,y+1; x,y
PRINT
PRINT "!*******************************"
PRINT "!"& p$(m)& names$(b)
PRINT "!*******************************"
WHEN EXCEPTION IN
OPEN #1: NAME p$(m)& names$(b),ACCESS INPUT
FOR L=1 TO 500 ! 最大表示行数
LINE INPUT #1,IF MISSING THEN EXIT FOR :w$
FOR i=1 TO LEN(w$)
IF
w$(i:i)< " " AND w$(i:i)<>CHR$(9) THEN CAUSE EXCEPTION 1
NEXT i
PRINT w$
NEXT L
USE
PRINT "******* テキストではない、表示の中止。"
END WHEN
CLOSE #1
LET bak=b
END SUB
!経線と緯線と使って、球体をワイヤーフレームで描画する
SET WINDOW -2,2,-2,2
FOR t=0 TO 90 STEP 15 !角度を等分割する
LET a=SIN(RAD(t)) !端付近:密、中央付近:疎
LET b=1
FOR i=0 TO 360 !経線 ※楕円を描く
LET x=a*COS(RAD(i))
LET y=b*SIN(RAD(i))
PLOT LINES: x,y;
NEXT i
PLOT LINES
NEXT t
FOR i=-180 TO 180 STEP 10 !緯線 ※水平線を描く
LET y=SIN(RAD(i)) !角度を等分割する
LET x=SQR(1-y^2) !極付近:密、0度付近:疎
PLOT LINES: -x,y; x,y
NEXT i
PLOT LINES
END
!楕円を重ねると球体に見える!?
SET WINDOW -2,2,-2,2
LET b=1
FOR a=0 TO 1 STEP 0.25
FOR i=0 TO 360 !楕円を描く
LET x=a*COS(RAD(i))
LET y=b*SIN(RAD(i))
PLOT LINES: x,y;
NEXT i
PLOT LINES
NEXT a
LET a=1
FOR b=0 TO 1 STEP 0.25
FOR i=0 TO 360 !楕円を描く
LET x=a*COS(RAD(i))
LET y=b*SIN(RAD(i))
PLOT LINES: x,y;
NEXT i
PLOT LINES
NEXT b
END
!ワイヤーフレームで曲面を描く SAMPLE\3DPLOT.BASを改修。
SUB rotx(x,y,z,a)
LET y0=y*cos(a)-z*sin(a)
LET z0=y*sin(a)+z*cos(a)
LET y=y0
LET z=z0
END SUB
SUB roty(x,y,z,a)
LET x0=x*cos(a)+z*sin(a)
LET z0=-x*sin(a)+z*cos(a)
LET x=x0
LET z=z0
END SUB
SUB rotz(x,y,z,a)
LET x0=x*cos(a)-y*sin(a)
LET y0=x*sin(a)+y*cos(a)
LET x=x0
LET y=y0
END SUB
SUB convert(x,y,z)
CALL rotz(x,y,z,RAD(-30))
CALL rotx(x,y,z,RAD(-70))
END SUB
SUB plotTo(x,y,z)
LET x1=x
LET y1=y
LET z1=z
CALL convert(x1,y1,z1)
PLOT LINES:x1,y1;
END SUB
SUB PenUp
PLOT LINES
END SUB
SUB PlotText(x,y,z,s$)
CALL convert(x,y,z)
PLOT TEXT ,AT x,y: s$
END SUB
!媒体変数表示
DEF fx(u,v)=COS(u)*SIN(v) !球 u=[0,2*PI],v=[0,PI] ※球座標(r,θ,φ)
DEF fy(u,v)=SIN(u)*SIN(v)
DEF fz(u,v)=COS(v)
SET WINDOW -2,2,-2,2
FOR f=0 TO 360 !フレーム・アニメーション
SET DRAW mode hidden !ちらつき防止(開始)
CLEAR
! 軸を描く
CALL PlotTo(0,0,0)
CALL PlotTo(2,0,0)
CALL PlotTo(0,0,0)
CALL PlotTo(0,2,0)
CALL PlotTo(0,0,0)
CALL PlotTo(0,0,2)
CALL PenUp
CALL PlotText(2,0,0,"x")
CALL PlotText(0,2,0,"y")
CALL PlotText(0,0,2,"z")
! 曲面を描く
FOR u=0 TO 360 STEP 15
FOR v=0 TO 180 STEP 15
LET x=fx(RAD(u),RAD(v))
LET y=fy(RAD(u),RAD(v))
LET z=fz(RAD(u),RAD(v))
CALL rotx(x,y,z,RAD(f))
CALL PlotTo(x,y,z)
NEXT v
CALL PenUp
NEXT u
FOR v=0 TO 180 STEP 30
FOR u=-1 TO 360 STEP 30
LET x=fx(RAD(u),RAD(v))
LET y=fy(RAD(u),RAD(v))
LET z=fz(RAD(u),RAD(v))
CALL rotx(x,y,z,RAD(f))
CALL PlotTo(x,y,z)
NEXT u
call PenUp
NEXT v
SET DRAW mode explicit !ちらつき防止(終了)
!WAIT DELAY 0.1
NEXT f
END
ASK DIRECTORY s$
PRINT "カレントdir.:"& s$
IF file$="" THEN
FILE GETNAME file$, "gif" ! マウスで、入力。
IF file$="" THEN
PRINT "入力ファイル名が、ありません。"
STOP
END IF
END IF
PRINT "入力ファイル:"& file$& " (変化しません)"
OPEN #1: NAME file$, ACCESS INPUT
CALL readCI( 6+2+2+1+1+1 +1+2+2+2+2+1 )
IF db$(1:6)<>"GIF87a" THEN
PRINT "対象GIFファイルでない。"
STOP
END IF
LET sflg=ORD(db$(11:11))
IF bitand8( sflg,BVAL("80",16) )>0 THEN
PRINT "Common_パレット は、すでにあります。"
STOP
END IF
LET pi$=db$(14:23)
LET pflg=ORD(pi$(10:10))
IF ORD( pi$(1:1) )<>BVAL("2C",16) OR bitand8( pflg,BVAL("80",16) )=0 THEN
PRINT "十進 BASIC の GIFファイルでない。"
STOP
END IF
FILE splitname(file$) path$, name$, ext$ ! ext$は語頭に"."含む。
PRINT "出力ファイル:"& path$& name$& "##"& ext$
PRINT "Ok?[Enter]"
CHARACTER INPUT k$
IF k$<>CHR$(13) THEN
PRINT "中止"
STOP
END IF
PRINT "処理中"
!----
OPEN #2: NAME path$& name$& "##"& ext$
ERASE #2
!----
PRINT "1)GIF_識別文字、スクリーン情報、"
PRINT " common_パレット情報(修正)、の転送。"
LET j= bitor8( bitand8(sflg,BVAL("70",16)), bitand8(pflg,BVAL("87",16)) )
LET db$(11:11)=CHR$(j)
PRINT #2: db$(1:13);
!----
PRINT "2)private_パレット、から"
PRINT " common_パレット、へ 転送。"
CALL readCI( 3*2^(MOD(pflg,8)+1) )
PRINT #2: db$;
!----
PRINT "3)画像情報(修正)、の転送。"
LET pi$(10:10)=CHR$(0)
PRINT #2: pi$;
PRINT " private_パレット、の削除。"
!----
PRINT "4)画像データ 〜 GIF 終端ブロック、の転送中。"
CALL readCI( 1000000 )
PRINT #2: db$;
!----
CLOSE #2
CLOSE #1
PRINT "終了"
!-------read binary cx bytes
SUB readCI(cx) ! cx=bytes size
LET db$=""
FOR i=1 TO cx
CHARACTER INPUT #1,IF MISSING THEN EXIT SUB :w9$
LET db$=db$& w9$
NEXT i
END SUB
!-------
FUNCTION bitand8(a,b)
LET b9$="00000000"
LET b8$=right$("0000000"& BSTR$(a,2),8)
LET b7$=right$("0000000"& BSTR$(b,2),8)
FOR b9=1 TO 8
IF b8$(b9:b9)="1" AND b7$(b9:b9)="1" THEN LET b9$(b9:b9)="1"
NEXT b9
LET bitand8=BVAL(b9$,2)
END FUNCTION
FUNCTION bitor8(a,b)
LET b9$="00000000"
LET b8$=right$("0000000"& BSTR$(a,2),8)
LET b7$=right$("0000000"& BSTR$(b,2),8)
FOR b9=1 TO 8
IF b8$(b9:b9)="1" OR b7$(b9:b9)="1" THEN LET b9$(b9:b9)="1"
NEXT b9
LET bitor8=BVAL(b9$,2)
END FUNCTION
!n進法での整数、小数(有限小数、循環小数)、分数の計算
OPTION ARITHMETIC RATIONAL
FUNCTION ExBVAL(x$,RADIX) !(RADIX)進法の数値を表現する文字列を10進法数値に変換する
IF RADIX<1 OR RADIX<>INT(RADIX) THEN
PRINT "基数は2以上の整数を指定してください。"; RADIX
STOP
END IF
CALL dec2frac(x$,RADIX, m,n) !小数を分数へ
LET ExBVAL=m/n
END FUNCTION
FUNCTION ExVAL(x$) !数値を表現する文字列を10進法数値に変換する
LET ExVAL=ExBVAL(x$,10)
END FUNCTION
!下位のルーチン
FUNCTION VAL1(x$,N) !N進法の数値 ※ASCIIコード表から
IF x$>"9" THEN
LET t=ORD(x$)-ORD("A")+10
ELSE
LET t=ORD(x$)-ORD("0") !※t=VAL(x$)でも可
END IF
IF t<0 OR t>=N THEN !0〜N-1の範囲かどうか確認する
PRINT x$;"は範囲外の値です。"
STOP
END IF
LET VAL1=t
END FUNCTION
SUB dec2frac(x$,RADIX, m,n) !(RADIX)進数数値を表現する文字列を10進法分数(m/n)に変換する
LET L=LEN(x$) !文字列長を得る
LET p=0 !有限小数の桁数
LET k=0 !循環節の桁数。有限小数の場合、0
LET A=0
LET cSGN=1 !仮数の符号
LET cSGN2=1 !指数部の符号
LET flag=0 !「整数」 ※数値の型
!書式 整数、小数: ±9{.}{E±9} | ±{9}.9{E±9}
! 分数: ±9/9、循環小数: ±{9}.{9}[9]
LET i=1 !数字列の読み込み位置
DO WHILE i<=L !上位の桁から順に
LET t$=UCASE$(x$(i:i))
IF t$="." THEN !小数点なら
IF flag<>0 THEN
PRINT "小数点の位置が不正です。"; x$
STOP
END IF
LET flag=1 !「有限小数」
ELSEIF t$="+" THEN !+符号なら
IF i<>1 THEN
PRINT "+符号の位置が不正です。"; x$
STOP
END IF
ELSEIF t$="-" THEN !−符号なら
IF i<>1 THEN
PRINT "−符号の位置が不正です。"; x$
STOP
END IF
LET cSGN=-1
ELSEIF (RADIX<14 AND t$="E") OR t$="@" THEN !指数部なら ※14進法以上は、E.E@E(E.E*E^Eの意)
IF flag>1 THEN !浮動小数点数か?
PRINT "仮数は 9{.}|{9}.9 形式ではありません。"; x$
STOP
END IF
IF i+1<=L THEN !指数部の符号を得る
LET t$=UCASE$(x$(i+1:i+1))
IF t$="+" THEN !+符号なら
LET i=i+1
ELSEIF t$="-" THEN !−符号なら
LET cSGN2=-1
LET i=i+1
END IF
END IF
IF i=L THEN !右端か?
PRINT "指数がありません。"; x$
STOP
END IF
LET flag=2 !「指数部あり」
LET B=A !save it as fraction
LET A=0 !exponent
ELSEIF t$="/" THEN !分数なら
IF flag<>0 THEN !整数か?
PRINT "分子は整数ではありません。"; x$
STOP
END IF
LET flag=3 !「分数」
LET B=A !save it as numerator
LET A=0 !denominator
ELSEIF t$="[" THEN !循環小数なら
IF flag<>1 THEN !小数部か?
PRINT "循環小数の開始位置が不正です。"; x$
STOP
END IF
LET flag=4 !「循環小数」
ELSEIF t$="]" THEN
IF i<>L THEN !右端か?
PRINT "循環小数の終了位置が不正です。"; x$
STOP
END IF
ELSE
LET A=A*RADIX+VAL1(t$,RADIX) !多項式(( … ((a[1]*RADIX+a[2])*RADIX+a[3])*RADIX … +a[i-2])*RADIX+a[i-1])*RADIX+a[i] ※左シフト
IF flag=1 THEN LET p=p+1
IF flag=4 THEN LET k=k+1
END IF
LET i=i+1 !次へ
LOOP
!PRINT A;B; flag;cSGN;cSGN2;p;k !debug
IF flag<2 THEN !有限小数(整数も含む)の場合
LET m=cSGN * A
LET n=RADIX^p
ELSEIF flag=2 THEN !指数部あり小数の場合
IF cSGN2*A< p THEN
LET m=cSGN * B
LET n=RADIX^(p-cSGN2*A)
ELSE
LET m=cSGN * B*RADIX^(cSGN2*A-p)
LET n=1
END IF
ELSEIF flag=3 THEN !分数の場合
IF A=0 THEN
PRINT "0で割ることはできません。"; x$
STOP
END IF
LET m=cSGN * B
LET n=A
ELSE !循環小数の場合
LET B=INT(A/RADIX^k)
LET m=cSGN * (A-B)
LET n=(RADIX^(k+p)-RADIX^p)
END IF
LET B=GCD(m,n) !最大公約数で分子と分母を約分する
LET m=m/B
LET n=n/B
END SUB
FUNCTION GCD(a,b) !最大公約数を求める
DO UNTIL b=0
LET r=MOD(a,b)
LET a=b
LET b=r
LOOP
LET GCD=a
END FUNCTION
LET Precision=1000 !循環節の最大桁数 ※必要に応じて変更のこと
DIM s(Precision) !循環節の候補
FUNCTION ExBSTR$(x,RADIX) !10進法数値式を(RADIX)進法で小数表示するときの文字列に変換する
IF RADIX<1 OR RADIX<>INT(RADIX) THEN
PRINT "基数は2以上の整数を指定してください。"; RADIX
STOP
END IF
CALL dec2frac(STR$(x),10, m,n) !小数を分数へ
LET b$=frac2dec$(m,n,RADIX) !分数を小数へ
IF RADIX<>10 THEN LET b$=b$&"("&STR$(RADIX)&")" !進法(RADIX)をつける
LET ExBSTR$=b$
END FUNCTION
FUNCTION ExSTR$(x) !10進法数値式を小数表示するときの文字列に変換する
LET ExSTR$=ExBSTR$(x,10) !指数つき小数と分数は、STR$を使う
!!!LET b$=ExBSTR$(x,10)
!!!IF POS(b$,"[")>0 THEN LET ExSTR$=b$ ELSE LET ExSTR$=STR$(x) !循環小数のみ採用する
END FUNCTION
!下位のルーチン
FUNCTION STR1$(x) !N進法の数字記号 ※ASCIIコード表から
IF x>9 THEN
LET STR1$=CHR$(x-10+ORD("A")) !ABCD…XYZ ※N88系はASC("A")
ELSE
LET STR1$=CHR$(x+ORD("0")) !0123…789 ※STR$(x)でも可
END IF
END FUNCTION
FUNCTION frac2dec$(m,n,RADIX) !10進法分数(m/n)を(RADIX)進数で小数表示するときの文字列に変換する
IF SGN(m)*SGN(n)<0 THEN LET cSGN$="-" ELSE LET cSGN$="" !符号を得る
LET aa=ABS(m)
LET b=ABS(n)
LET t=GCD(aa,b) !最大公約数で分子と分母を約分する
LET aa=aa/t
LET b=b/t
!!!PRINT aa;b;t !debug
!整数部
LET a=INT(aa/b) !小数部を削除する
LET b$="" !変換後の数
DO WHILE a>=RADIX !a=b[k]*RADIX^k+b[k-1]*RADIX^(k-1)+ … +b[1]*RADIX^1+b[0]*RADIX^0より
LET b$=STR1$(MOD(a,RADIX))&b$ !一の位から求まる
LET a=INT(a/RADIX) !次の桁へ ※右シフト
LOOP
LET b$=STR1$(a)&b$
!小数部
LET aa=MOD(aa,b) !整数部を削除する
LET k=0 !小数部の桁数
DO UNTIL aa=0 !小数第1位から順に
LET k=k+1
IF k>MIN(b,Precision) THEN !循環小数によるループを回避する
PRINT "変換を打ち切りました。"
EXIT DO
END IF
IF k=1 THEN !初回のみ
LET b$=b$&"." !小数点をつける
LET p=LEN(b$) !位置を記録しておく
ELSE
FOR i=1 TO k-1 !循環したかどうか確認する
IF s(i)=aa THEN EXIT DO !循環節なら、終了!
NEXT i
END IF
LET s(k)=aa !小数第k位以降(未展開の小数部)の数を記録する
LET aa=aa*RADIX !左シフトして、商を求める
LET a=INT(aa/b)
LET b$=b$&STR1$(a) !a=S[-1]*RADIX^(-1)+S[-2]*RADIX^(-2)+ … +S[-(k-1)]*RADIX^(-(k-1))+S[-k]*RADIX^(-k)より
LET aa=MOD(aa,b) !剰余を求めて、次の桁へ
LOOP
IF aa=0 THEN !有限小数(整数も含む)なら
LET p=k !有限小数の桁数
LET k=0 !循環節の桁数
ELSE !循環小数なら
LET b$(i+p:i+p)="["&b$(i+p:i+p) !開始記号を挿入
LET b$=b$&"]" !終了記号
LET p=i-1 !有限小数の桁数
LET k=k-i !循環節の桁数
END IF
LET frac2dec$=cSGN$&b$ !-9.9[9] 形式
END FUNCTION
!------------------------------ ここまでがサブルーチン
!● 0.[13](4)を10進法の分数で表現する 答え 7/15
!※等比数列の和 初項 0.13(4)=1/4^1+3/4^2、公比 0.01(4)=1/4^2
! LET a = 0. + (1/4^1+3/4^2)/(1-1/4^2)
! PRINT a
PRINT ExBVAL("0.[13]",4)
!● 1/7を3進法の小数(循環する)で表現する 答え 0.[010212](3)
PRINT ExBSTR$(1/7,3)
!● 0.1[23] ÷ 0.[14] の結果を循環小数で表せ。 答え 0.8[714285]
!筆算
! x=0.1[23]とすると
! 100*x-x=12.3[23]-0.1[23]=12.2 ∴99*x=122/10 ∴x=61/495
LET t=ExVAL("0.1[23]") / ExVAL("0.[14]")
PRINT t, ExSTR$(t)
!● 3/7 を小数で表したとき、小数第800位の数字を求めよ。 答え 2
LET x$=ExSTR$(3/7) !0.[428571]
LET y$=x$(POS(x$,"[")+1:POS(x$,"]")-1) !循環節を切り出す
LET x=MOD(800,LEN(y$)) !800/6=133 余り 2
PRINT y$(x:x)
END
! GIF ファイルの解析ツール
!-------
OPTION CHARACTER BYTE
!
FILE GETNAME file$, "gif"
IF file$="" THEN
PRINT "入力ファイル名が、ありません。"
STOP
END IF
PRINT "入力ファイル:"& file$
!
OPEN #1: NAME file$, ACCESS INPUT
PRINT "---------"
CALL gif_head
DO
CALL blocks_main
LOOP UNTIL b1$=CHR$(BVAL("3B",16))
PRINT "GIF 終端ブロック"
CALL dump(b1$,16,"block label")
PRINT "---------"
CLOSE #1
IF c_p$>"" OR p_p$="" OR im$>"" OR ap$>"" OR co$>"" OR tx$>"" THEN STOP
PRINT "十進BASIC 出力の GIF ファイルのようです。"
!----
SUB gif_head
LET h$=""
CALL readb( h$,13 )
IF h$(1:3)="GIF" THEN PRINT "GIF ヘッダー" ELSE CALL error
LET Xsw= ORD(h$( 8: 8))*256+ORD(h$(7:7))
LET Ysw= ORD(h$(10:10))*256+ORD(h$(9:9))
LET sflg= ORD(h$(11:11)) ! スクリーン情報のフラグ
LET aspect=ORD(h$(13:13))
LET b$=right$("0000000"& BSTR$(sflg,2) ,8)
LET colpix=2^(BVAL(b$(2:4),2)+1)
LET compal=2^(BVAL(b$(6:8),2)+1)
CALL dumpASC(h$(1:6),8) ! GIF識別文字
CALL dump(h$( 7: 8),16,"screen X_width "& STR$(Xsw))
CALL dump(h$( 9:10),16,"screen Y_width "& STR$(Ysw))
CALL dump(h$(11:11),16,"flags "& b$ )
PRINT TAB(12);b$(1:1);":common_palette on=1/off=0"
PRINT TAB(10);b$(2:4);":colors/pixel 2^(";b$(2:4);"b+1)= ";STR$(colpix)
PRINT TAB(12);b$(5:5);":sort on=1/off=0 頻度の色順( outer use)"
PRINT TAB(10);b$(6:8);":common_palette colors 2^(";b$(6:8);"b+1)= ";STR$(compal)
CALL dump(h$(12:12),16,"back_ground color_code")
IF aspect=0 THEN LET b$=".." ELSE LET b$=STR$(aspect)
CALL dump(h$(13:13),16,"アスペクト比 pixel H:V=("& b$& "+15):64 =1:1( 00)" )
CALL palette("common_パレット", c_p$, sflg)
END SUB
!----
SUB blocks_main
LET b1$=""
CALL readb( b1$, 1)
IF b1$=CHR$(BVAL("21",16)) THEN !追加データ・ブロック
CALL option_block
ELSEIF b1$=CHR$(BVAL("2C",16)) THEN !画像ブロック
CALL picture_block
ELSEIF b1$=CHR$(BVAL("3B",16)) THEN !GIF 終端ブロック
ELSE
CALL error
END IF
END SUB
!---追加データ・ブロック。
SUB option_block
PRINT "追加データ・ブロック"
CALL readb( b1$,1) ! w9$= readb_last_byte
IF w9$=CHR$(BVAL("F9",16)) THEN
LET im$=b1$
CALL dump(im$,16,"イメージコントロール・ブロック")
CALL blocksNP1(im$)
LET iflg=ORD(im$(4:4)) ! フラグ
LET imtm=ORD(im$(6:6))*256+ORD(im$(5:5))
LET tcol=ORD(im$(7:7))
LET b$=right$("0000000"& BSTR$(iflg,2),8)
CALL dump(im$(4:4),16,"flags "& b$ )
PRINT TAB(10);b$(1:3);":blank"
PRINT TAB(10);b$(4:6);":"
PRINT TAB(14);"000=none( OR )"
PRINT TAB(14);"001= OR( same as 000)"
PRINT TAB(14);"010=remove all before( paint screen_BG before)"
PRINT TAB(14);"011=remove last picture before"
PRINT TAB(12);b$(7:7);":user click on=1/off=0"
PRINT TAB(12);b$(8:8);":透過GIFの透明色のスイッチ on=1/off=0"
CALL dump(im$(5:6),16,"アニメーションGIFのフレーム表示時間(10ms単位) "& STR$(imtm) )
CALL dump(im$(7:7),16,"透過GIFの透明色 "& STR$(tcol) )
CALL blocks(im$)
ELSEIF w9$=CHR$(BVAL("FE",16)) THEN
LET co$=b1$
CALL dump(co$,16,"コメント・ブロック")
CALL blocksASC(co$,100)
ELSEIF w9$=CHR$(BVAL("FF",16)) THEN
LET ap$=b1$
CALL dump(ap$,16,"アプリケーション・ブロック")
CALL blocksASC(ap$,1)
IF ap$(4:11)="NETSCAPE" THEN
CALL blocksNP1(ap$)
CALL dump(ap$(16:16),16,"constant 1")
LET rept=ORD(ap$(18:18))*256+ORD(ap$(17:17))
CALL
dump(ap$(17:18),16,"animation repeat number "& STR$(rept)& "
(0=endless)" )
END IF
CALL blocksASC(ap$,100)
ELSEIF w9$=CHR$(BVAL("01",16)) THEN
LET tx$=b1$
CALL dump(tx$,16,"テキスト・イメージ・ブロック")
CALL blocksASC(tx$,100)
ELSE
CALL error
END IF
END SUB
SUB blocksNP1(d$)
CALL
readb(d$,1)
! w9$= readb_last_byte ! =block Size
CALL dump(w9$,16,"block size")
IF w9$=CHR$(0) THEN EXIT SUB ! block End
CALL readb(d$,ORD(w9$)) ! block data
END SUB
SUB blocks(d$)
DO
CALL
readb(d$,1)
! w9$= readb_last_byte ! =block Size
CALL dump(w9$,16,"block size")
IF w9$=CHR$(0) THEN EXIT SUB ! block End
LET s=LEN(d$)
CALL readb(d$,ORD(w9$)) ! block data
CALL dump(d$(s+1:LEN(d$)),16,"")
LOOP
END SUB
SUB blocksASC(d$,n) !n=ブロック数の上限
FOR n=1 TO n
CALL
readb(d$,1)
! w9$= readb_last_byte ! =block Size
CALL dump(w9$,16,"block size")
IF w9$=CHR$(0) THEN EXIT SUB ! block End
LET s=LEN(d$)
CALL readb(d$,ORD(w9$)) ! block data
CALL dumpASC(d$(s+1:LEN(d$)),8)
NEXT n
END SUB
SUB readb(d$,cx) !cx=bytes size
FOR i=1 TO cx
CHARACTER INPUT #1,IF MISSING THEN EXIT FOR :w9$
LET d$=d$& w9$
NEXT i
IF i<=cx THEN CALL error
END SUB
SUB picture_block
PRINT "画像ブロック"
LET pi$=b1$
CALL readb( pi$,9) ! w9$= readb_last_byte
CALL dump(pi$(1:1),16,"block label")
LET Xp0=ORD(pi$(3:3))*256+ORD(pi$(2:2))
LET Yp0=ORD(pi$(5:5))*256+ORD(pi$(4:4))
LET Xpw=ORD(pi$(7:7))*256+ORD(pi$(6:6))
LET Ypw=ORD(pi$(9:9))*256+ORD(pi$(8:8))
CALL dump(pi$(2:3),16,"picture.X0_position left "& STR$(Xp0))
CALL dump(pi$(4:5),16,"picture.Y0_position top "& STR$(Yp0))
CALL dump(pi$(6:7),16,"picture.X_width "& STR$(Xpw))
CALL dump(pi$(8:9),16,"picture.Y_width "& STR$(Ypw))
LET pflg=ORD(pi$(10:10)) ! 画像情報のフラグ
LET b$=right$("0000000"& BSTR$(pflg,2),8)
LET pripal=2^(BVAL(b$(6:8),2)+1)
CALL dump(pi$(10:10),16,"flags "& b$ )
PRINT TAB(12);b$(1:1);":private_palette on=1/off=0"
PRINT TAB(12);b$(2:2);":interrace on=1/off=0, 1~step8 5~step8 3~step4 2~step2"
PRINT TAB(12);b$(3:3);":sort on=1/off=0 頻度の色順( outer use)"
PRINT TAB(11);b$(4:5);":blank"
PRINT TAB(10);b$(6:8);":private_palette colors 2^(";b$(6:8);"b+1)= ";STR$(pripal)
CALL palette("private_パレット", p_p$, pflg)
!---
PRINT "画像データ"
LET pda$=""
CALL readb( pda$,1)
CALL dump(pda$,16,"最小データ・ビット長")
!--- LZW データ(size:data, size:data, … 0 )
CALL blocks(pda$)
END SUB
SUB palette(n$, p$, pf)
PRINT n$;
LET p$=""
IF INT(pf/128)>0 THEN ! pf AND 0x80
PRINT
CALL readb(p$, 3*2^(MOD(pf,8)+1)) ! pf AND 0x07
CALL dump(p$,3,"R G B")
ELSE
PRINT "は、有りません。"
END IF
END SUB
SUB error
beep
PRINT "File Error Stop"
STOP
END SUB
!-------
FUNCTION bitand8(a,b)
LET b9$="00000000"
LET b8$=right$("0000000"& BSTR$(a,2),8)
LET b7$=right$("0000000"& BSTR$(b,2),8)
FOR b9=1 TO 8
IF b8$(b9:b9)="1" AND b7$(b9:b9)="1" THEN LET b9$(b9:b9)="1"
NEXT b9
LET bitand8=BVAL(b9$,2)
END FUNCTION
FUNCTION bitor8(a,b)
LET b9$="00000000"
LET b8$=right$("0000000"& BSTR$(a,2),8)
LET b7$=right$("0000000"& BSTR$(b,2),8)
FOR b9=1 TO 8
IF b8$(b9:b9)="1" OR b7$(b9:b9)="1" THEN LET b9$(b9:b9)="1"
NEXT b9
LET bitor8=BVAL(b9$,2)
END FUNCTION
!-------
SUB dump(d$,m,t$)
FOR j=1 TO LEN(d$) STEP m
LET ww$=right$("000"& BSTR$(adr,16),4)& " "
FOR i=j TO MIN(j+m-1, LEN(d$))
LET ww$=ww$& " "& right$("0"& BSTR$( ORD(d$(i:i)),16),2)
LET adr=adr+1
NEXT i
IF t$>"" AND j<=m THEN LET ww$=ww$& " ;"& t$
PRINT ww$ !行単位、テキスト画面のピカつき減少、高速。
NEXT j
END SUB
SUB dumpASC(d$,m)
FOR j=1 TO LEN(d$) STEP m
LET ww$=right$("000"& BSTR$(adr,16),4)& " "
FOR i=j TO MIN(j+m-1, LEN(d$))
LET ww$=ww$& " "& right$("0"& BSTR$( ORD(d$(i:i)),16),2)
LET adr=adr+1
NEXT i
LET ww$=ww$& REPEAT$(" ",3*m+6-LEN(ww$))& ";"""
FOR i=j TO MIN(j+m-1, LEN(d$))
IF " "<=d$(i:i) THEN LET ww$=ww$& d$(i:i) ELSE LET ww$=ww$& "."
NEXT i
LET ww$=ww$& """"
PRINT ww$
NEXT j
END SUB
!論理式の計算
DEF AND3(a,b,c)=AND(AND(a,b),c) !3変数以上の場合
DEF AND4(a,b,c,d)=AND(AND(a,b),AND(c,d))
DEF OR3(a,b,c)=OR(OR(a,b),c)
DEF OR4(a,b,c,d)=OR(OR(a,b),OR(c,d))
LET C1=NT(0) !1 ※−1のビットパターン
!------------------------------ ここまでがマクロの定義
LET N=3 !変数の数 ※1〜5
LET A=BOOL(N,1) !N個の変数の1番目
LET B=BOOL(N,2)
LET C=BOOL(N,3)
!LET D=BOOL(N,4)
!LET E=BOOL(N,5)
LET nA=NT(A) !A' 補元
LET nB=NT(B)
LET nC=NT(C)
!LET nD=NT(D)
!LET nE=NT(E)
!●論理式の真理値表をつくる
PRINT BitPTN$(N, A); ":A"
PRINT BitPTN$(N, B); ":B"
PRINT BitPTN$(N, C); ":C"
LET f=OR3(AND3(A,B,C), AND3(A,nB,C), AND3(A,B,nC))
PRINT BitPTN$(N, f); ":ABC+AB'C+ABC'"
PRINT
!●論理式を主加法標準展開、主乗法標準展開する
LET f=OR(A,AND(B,C))
!PRINT BitPTN$(N, f); ":A+BC"
CALL PrintPDCF(N,f)
CALL PrintPCCF(N,f)
PRINT
!●クワイン・マクラスキー法(Quine-McCluskey algorithm)で式を簡単化する
!ステップ0 論理式の真理値表をつくる
LET f=OR4(AND3(nA,B,C),AND3(A,nB,C),AND3(A,B,nC),AND3(A,B,C))
!PRINT BitPTN$(N, f); ":A'BC+AB'C+ABC'+ABC"
!ステップ1 論理式を最小項で記述する(主加法標準展開)
DIM Term$(2^N) !最小項のビットパターン
LET CntOfTerm=0 !最小項の数
FOR i=0 TO 2^N-1 !真理値表を2進法の数とみなして小さい順に
IF Bit(f,i)=1 THEN !最小項なら
LET CntOfTerm=CntOfTerm+1
LET Term$(CntOfTerm)=right$(REPEAT$("0",N-1)&BSTR$(i,2),N) !ビットパターンは、…DCBA順
END IF
NEXT i
!FOR i=1 TO CntOfTerm !debug
! PRINT Term$(i)
!NEXT i
IF CntOfTerm=0 THEN !すべて0なら、終了!
PRINT "0"
STOP
ELSEIF CntOfTerm=2^N THEN !すべての1なら、終了!
PRINT "1"
STOP
END IF
!ステップ2 AB+AB'=Aを使って、最小項の変数を減らす
DIM wTerm$(100) !作業用にコピーする
FOR i=1 TO CntOfTerm
LET wTerm$(i)=Term$(i)
NEXT i
LET wCntOfTerm=CntOfTerm
DIM Term9$(2^N) !主項のビットパターン
LET CntOfTerm9=0 !主項の数
DO
DIM CHK(100) !圧縮の有無
MAT CHK=ZER
LET CntOfCompTRM=0 !圧縮された項の数
FOR i=1 TO wCntOfTerm-1 !すべての組合せで考慮する
FOR j=i+1 TO wCntOfTerm
LET CntOf1=0 !「1」の数
FOR k=1 TO N !ビット単位の排他的論理和を求める
LET t1$=wTerm$(i)(k:k)
LET t2$=wTerm$(j)(k:k)
IF (t1$="1" AND t2$="0") OR (t1$="0" AND t2$="1") THEN !「1」とする
LET CntOf1=CntOf1+1
LET PosOf1=k !消去される変数の位置
ELSEIF (t1$="0" AND t2$="0") OR (t1$="1" AND t2$="1") THEN !「0」とする
!skip it
ELSEIF (t1$="-" AND t2$="-") THEN !マスク・ビットなら
!skip it
ELSE !片方がマスク・ビットなら、候補ではない!
LET CntOf1=N
EXIT FOR
END IF
NEXT k
IF CntOf1=1 THEN !AB+AB'=A(ハミング距離が1)より、消去する
LET t$=wTerm$(i) !ビットパターン
LET t$(PosOf1:PosOf1)="-" !その変数を消去する
LET CHK(i)=1 !圧縮あり
LET CHK(j)=1
DIM CompTRM$(100)
FOR k=1 TO CntOfCompTRM !同じ項があるか確認する
IF t$=CompTRM$(k) THEN EXIT FOR
NEXT k
IF k>CntOfCompTRM THEN !なけらば、新規に登録する
LET CntOfCompTRM=CntOfCompTRM+1
LET CompTRM$(CntOfCompTRM)=t$
!PRINT i;j; t$ !debug
END IF
END IF
NEXT j
NEXT i
LET Cnt=0 !今回圧縮できなかった項の数
FOR i=1 TO wCntOfTerm !圧縮されないものは、主項となる
IF CHK(i)=0 THEN
LET Cnt=Cnt+1
LET CntOfTerm9=CntOfTerm9+1 !主項として記録する
LET Term9$(CntOfTerm9)=wTerm$(i)
END IF
NEXT i
IF Cnt=wCntOfTerm THEN EXIT DO !すべて圧縮できなければ、終了!
FOR i=1 TO CntOfCompTRM !次へ
LET wTerm$(i)=CompTRM$(i) !copy it
NEXT i
LET wCntOfTerm=CntOfCompTRM
LOOP
!ステップ3 主項表を使って冗長な主項を削除する
!ステップ3−1 主項表をつくる
DIM TT(CntOfTerm9,CntOfTerm) !主項表(図) ※TT(主項,最小項)
MAT TT=ZER
FOR i=1 TO CntOfTerm9 !最小項を包含する主項にチェックを入れる
FOR j=1 TO CntOfTerm
FOR k=1 TO N
LET t$=Term9$(i)(k:k)
IF t$<>"-" THEN !マスク・ビット以外が不一致なら、終了!
IF t$<>Term$(j)(k:k) THEN EXIT FOR
END IF
NEXT k
IF k>N THEN LET TT(i,j)=1 !すべてのビットが一致すれば、包含する
NEXT j
NEXT i
!MAT PRINT TT; !debug
!ステップ3−2 主項表から必須項を探す
DIM CHK2(CntOfTerm9) !必須項としてチェックする
MAT CHK2=ZER
MAT CHK=ZER
FOR j=1 TO CntOfTerm !主項表から必須項を探す
LET Cnt=0
FOR i=1 TO CntOfTerm9 !列で走査して、「1」が1つの列を見つける
IF TT(i,j)=1 THEN
LET Cnt=Cnt+1
LET PosOf1=i !行位置
END IF
NEXT i
IF Cnt=1 THEN !1つのものは、必須項とする
LET CHK2(PosOf1)=1
FOR k=1 TO CntOfTerm !必須項だけで最小項を包含するか(冗長性)
LET CHK(k)=OR(CHK(k),TT(PosOf1,k))
NEXT k
END IF
NEXT j
!MAT PRINT CHK; !debug
!MAT PRINT CHK2;
!ステップ3−3 必須項と選択項の組み合わせで過不足なく項を選ぶ
DO
FOR j=1 TO CntOfTerm !包含されていない箇所を探す
IF CHK(j)=0 THEN EXIT FOR
NEXT j
IF j>CntOfTerm THEN EXIT DO !必須項+選択項で最小項を包含するなら、終了!
FOR i=1 TO CntOfTerm9 !その箇所を選択項で埋める
IF TT(i,j)=1 THEN !行位置
LET CHK(j)=2
LET CHK2(i)=2 !選択項に加える
EXIT FOR
END IF
NEXT i
!MAT PRINT CHK; !debug
!MAT PRINT CHK2;
LOOP
!結果を表示する
FOR i=1 TO CntOfTerm9
IF CHK2(i)>0 THEN !必須項または選択項なら
PRINT "+";
FOR k=0 TO N-1 !変数へ
SELECT CASE Term9$(i)(N-k:N-k) !ビットパターンを得る ※…DCBA順
CASE "0"
PRINT CHR$(k+ORD("A"));"'"; !否定
CASE "1"
PRINT CHR$(k+ORD("A"));
CASE ELSE !"-"
END SELECT
NEXT k
END IF
NEXT i
PRINT
END
EXTERNAL FUNCTION BOOL(N,i) !真理値表での変数A〜Zのビットパターン(2^N 桁)を求める
LET t$=REPEAT$("1",2^(i-1))&REPEAT$("0",2^(i-1)) !11…100…0
LET BOOL=BVAL(REPEAT$(t$,2^(N-i)),2) !A,B,C,…
END FUNCTION
!出力関連
EXTERNAL SUB PrintPDCF(N,f) !真理値表を主加法標準形(選言標準形)で出力する
FOR i=0 TO 2^N-1
IF Bit(f,i)=1 THEN !最小項
PRINT "+";
FOR x=0 TO N-1
PRINT CHR$(x+ORD("A")); !変数名
IF Bit(i,x)=0 THEN PRINT "'"; !否定記号
NEXT x
END IF
NEXT i
PRINT
END SUB
EXTERNAL SUB PrintPCCF(N,f) !真理値表を主乗法標準形(連言標準形)で出力する
FOR i=0 TO 2^N-1
IF Bit(f,i)=0 THEN !最大項
PRINT "(";
FOR x=0 TO N-1
PRINT "+";
PRINT CHR$(x+ORD("A")); !変数名
IF Bit(i,x)=1 THEN PRINT "'"; !否定記号
NEXT x
PRINT ")";
END IF
NEXT i
PRINT
END SUB
!補助ルーチン
EXTERNAL FUNCTION Bit(x,m) !mビット目を得る 0,1
LET Bit=MOD(INT(x/2^m),2)
END FUNCTION
EXTERNAL FUNCTION BitPTN$(N,a) !ビットパターン(2^N 桁)を求める
IF a>=0 THEN
LET a$=REPEAT$("0",2^N-1)&BSTR$(a,2)
ELSE
LET a$=BSTR$(a+2^32,2)
END IF
LET BitPTN$=right$(a$,2^N)
END FUNCTION
!論理演算
EXTERNAL FUNCTION AND(a,b) !整数a,bのビット単位での論理積を求める
LET c=0
FOR i=0 TO 31
LET aa=MOD(a,2)
LET a=(a-aa)/2
LET bb=MOD(b,2)
LET b=(b-bb)/2
LET c=c+MIN(aa,bb)*2^i
NEXT i
IF c>=2^31 THEN LET c=c-2^32
LET AND=c
END FUNCTION
EXTERNAL FUNCTION OR(a,b) !整数a,bのビット単位での論理和を求める
LET c=0
FOR i=0 TO 31
LET aa=MOD(a,2)
LET a=(a-aa)/2
LET bb=MOD(b,2)
LET b=(b-bb)/2
LET c=c+MAX(aa,bb)*2^i
NEXT i
IF c>=2^31 THEN LET c=c-2^32
LET OR=c
END FUNCTION
EXTERNAL FUNCTION NT(a) !整数aのビット単位での論理否定を求める ※NOTは予約語のため
LET NT=-1-a
END FUNCTION
LET ofile$="DecAnima.GIF" ! 削除すると、ダイアログ・ボックス入力。
ASK DIRECTORY s$
IF ofile$>"" THEN PRINT "カレント DIR:"& s$ ELSE file getname ofile$, "gif"
PRINT "出力ファイル:"& ofile$
IF ofile$>"" THEN PRINT "上書き。又は作成されます。…"& "Ok?[Enter]"
IF ofile$>"" THEN CHARACTER INPUT k$
IF ofile$="" OR k$<>CHR$(13) THEN
PRINT "中止"
STOP
END IF
!-----------
! 射影変換 ( SAMPLE\TRANSFO9.BAS から、拝借)
DIM T(4,4),m(501,501)
MAT T=IDN
PICTURE House
SET AREA COLOR 15
PLOT AREA: 0, 1;
0, 0; 2, 0;
2, 1 !壁
SET AREA COLOR 2
PLOT AREA: -0.6,1; 2.6, 1; 2, 2; 0, 2 !屋根
SET AREA COLOR 10
PLOT AREA: 0.1, 0; 0.1,0.8; 0.5,0.8; 0.5, 0 !ドア
SET AREA COLOR 5
PLOT AREA: 1.4,0.4; 1.9,0.4; 1.9,0.8; 1.4,0.8 !窓
SET AREA COLOR 12
PLOT AREA: 1.7, 2; 1.7,2.3; 1.5,2.3; 1.5, 2 !煙突
END PICTURE
SET WINDOW -5,5,-5,5
ASK PIXEL SIZE (-1.1,4.3 ; 4.6,-.5) Xw,Yw
MAT m=ZER(Xw,Yw)
!screen& picture.xw =Xw
!screen& picture.yw =Yw
LET obits0=4 !( 2= 2色~4色, 3= 8色, 4=16色, … 8=256色)
!
CALL gif_header
CALL applica_blk(0) !repeat number, 0=end less
!
LET N000=2^obits0 !encoder colors max. …予約登録番号最大値+1
LET t_max= 2000 ! 表示のthead より大きい程度に、小さいと辞書クリアー頻度増。
DIM dic_0(0 TO t_max, 0 TO N000-1), dic_1(0 TO t_max, 0 TO N000-1) !逆引き辞書
!
FOR i9=-PI TO 0*PI+.01 STEP PI/2
LET a=(1+COS(i9))/2
LET T(1,4)= .1*a
LET T(2,4)=-.1*a
SET DRAW mode hidden
CLEAR
DRAW axes
SET AREA COLOR 6 !透過色に使用
PLOT AREA: -1.1,-.5; 4.6,-.5; 4.6,4.3; -1.1,4.3
DRAW House WITH T*ROTATE(-PI/20*a)*SCALE(1.72)
ASK PIXEL ARRAY (-1.1,4.3) m
SET DRAW mode explicit
!----
READ dly
DATA 140,20,100
!CALL img_ctl_blk( dly,BVAL("00001000",2), 6) !透過させない、全表示
CALL img_ctl_blk( dly,BVAL("00001001",2), 6) !表示時間(x10ms),iflg,透過色
CALL picture_blk
CALL picture_data
!----
NEXT i9
CALL gif_terminater
!---------
!画像配列 m(1~Xw,1~Yw) !! 注意 x,y の順 mat read m(y,x)
SUB inppix !! ask pixel array(x0,y0) m(x,y)
LET lx=lx+1
IF Xw< lx THEN
LET lx=1
LET ly=ly+1
END IF
IF ly<=Yw THEN LET bx=m(lx,ly) ! data on bx
END SUB
SUB picture_data
PRINT #1: CHR$(obits0); !最小データービット長 …予約登録番号の最大ビット長
LET blkfull=255 !block size max.(~~255)
LET bitfull=12 ! LZW bits max.(~~ 12)
CALL LZW_encoder
CALL outcode !flush registered dic.number on ax
LET ax=N000+1 !code end
CALL outcode
CALL out_flush
PRINT #1: CHR$(0); !block size 0 (end)
END SUB
SUB LZW_encoder
LET lx=1 -1 !画像配列 m(1~Xw,1~Yw)
LET ly=1
CALL inppix !data on bx
LET pdata$="" !clear output bytes buffer
LET oacc$="" !clear output bits buffer
LET owidth=obits0+1 !starting bit width
DO
LET ax=N000 !reset code
CALL outcode
MAT dic_0=ZER !clear dic.number
MAT dic_1=ZER !clear dic.chain
LET
thead=1 !reset
make_table pointer
LET dicnum=N000+2 !reset dictionary new number
LET owidth=obits0+1 !starting bit width
DO
LET
di=0 !top
table
LET dic_0(di,bx)=bx
DO
LET
ax=dic_0(di,bx) !---latch last chained register
IF
dic_1(di,bx)>0 THEN LET di=dic_1(di,bx) ELSE CALL make_table
CALL
inppix !
next bx
IF Yw< ly THEN EXIT SUB
LOOP UNTIL dic_0(di,bx)=0 !---until no register
LET dic_0(di,bx)=dicnum ! new register, bx=tail
CALL
outcode !write
last register
LET owidth=LEN( BSTR$(dicnum,2) ) ! remake owidth
LET dicnum=dicnum+1
LOOP UNTIL dicnum>2^bitfull-1 OR thead>t_max !bits full or dic.full
LOOP
END SUB
SUB make_table
LET dic_1(di,bx)=thead !chained table pointer
LET di=thead !new table head
LET thead=thead+1
END SUB
SUB outcode
LET oacc$=right$("00000000000"& BSTR$(ax,2),owidth)& oacc$
DO WHILE LEN(oacc$)>=8
LET pdata$=pdata$& CHR$(BVAL(right$(oacc$,8),2))
LET oacc$=oacc$(1:LEN(oacc$)-8)
IF LEN(pdata$)=blkfull THEN CALL bw_sub
LOOP
END SUB
SUB bw_sub
PRINT #1: CHR$(LEN(pdata$)); pdata$;
LET pdata$=""
PRINT "thead=";thead;" dicnum=";dicnum !--monitor
END SUB
SUB out_flush
IF oacc$<>"" THEN LET pdata$=pdata$& CHR$(BVAL(oacc$,2) )
LET oacc$=""
IF pdata$>"" THEN CALL bw_sub
PRINT "------" !--monitor
END SUB
!=============
SUB gif_header
PRINT "処理中"
OPEN #1: NAME ofile$
ERASE #1
PRINT #1: "GIF89a";
CALL prt_2dw( Xw,Yw )
! ---sflg---
! 1: common-palet-ON
!xxx: colors_bits/pixel 2^(xxxb+1)
! 0: sort-OFF
!xxx: colors_bits/common-palet 2^(xxxb+1)
LET sflg=BVAL("10000000",2)+(obits0-1)*16+(obits0-1)
PRINT #1: CHR$(sflg);
PRINT #1: CHR$(0); ! back ground color
PRINT #1: CHR$(0); ! アスペクト比 if n=0 then 1:1 else H:V=(n+15):64
! common_palette
FOR i=0 TO 2^obits0-1
ASK COLOR MIX(i) r,g,b
PRINT #1: CHR$(r*255);CHR$(g*255);CHR$(b*255); ! R G B
NEXT i
END SUB
!60の場合
PRINT 1+2+3+4+5+6+10+12+15+20+30+60
!●実際に求めて、その和を計算する
LET n=60 !求める数
LET s=0 !和
LET c=0 !個数
FOR f=1 TO SQR(n) !個数の半分まで
IF MOD(n,f)=0 THEN !割り切れるなら
IF n/f=f THEN !商と割った数が同じとき、1つ
!PRINT f
LET s=s+f
LET c=c+1
ELSE !商と割った数が異なるとき、ペアで求まる
!PRINT f; n/f
LET s=s+f+n/f
LET c=c+2
END IF
END IF
NEXT f
PRINT "和=";s, "個数=";c
!●素因数分解
! n=p^a*q^b*r^c* … 、素数p,q,r,…、整数a,b,c,… なら
! 和 (p^0+p^1+p^2+ … +p^a)*(q^0+q^1+q^2+ … +q^b)*(r^0+r^1+r^2+ … +r^c)* …
! 個数 (a+1)*(b+1)*(c+1)* …
!60=2^2*3^1*5^1 より
PRINT (2^0+2^1+2^2)*(3^0+3^1)*(5^0+5^1) !和
PRINT (2+1)*(1+1)*(1+1) !個数
!また、カッコの中は等比数列より ※和Sn=a*(1-r^n)/(1-r)、初項a、公比r、項数n
LET t1=1*(1-2^3)/(1-2) !2^0+2^1+2^2
LET t2=1*(1-3^2)/(1-3) !3^0+3^1
LET t3=1*(1-5^2)/(1-5) !5^0+5^1
PRINT t1*t2*t3
!●素因数分解のプログラムに上記の算出方法を組込む
LET n=60 !求める数
LET s=1 !和
LET c=1 !個数
LET f=2
DO UNTIL f>SQR(n)
LET k=0
DO WHILE MOD(n,f)=0 !割り切れるなら
!PRINT f;
LET k=k+1 !個数
LET n=n/f
LOOP
LET s=s * 1*(1-f^(k+1))/(1-f) !等比数列の和 Σ[i=0,k+1]f^i
LET c=c * (k+1) !0,1,2,…,k
LET f=f+1 !次へ
LOOP
IF n>1 THEN !残りの因数
!PRINT n
LET s=s * 1*(1-n^(1+1))/(1-n)
LET c=c * (1+1)
END IF
PRINT "和=";s, "個数=";c
! LZW エンコーダーと、デコーダー
!-----------
OPTION CHARACTER byte
DIM m(501,501)
LET obits0=2 !( 2= 2色~4色, 3= 8色, 4=16色, … 8=256色)
LET N000=2^obits0 ! 色数(予約の登録番号最大+1)
!
LET t_max= 1000 !=使われた色数x辞書への登録文字の長さ。(不詳)【逆引き辞書】
! !
小さいと辞書クリアー頻度増し、圧縮出力サイズは、悪化するが、
! ! その分、復元側も、辞書のメモリー消費は、減る。
DIM dic_0(0 TO t_max, 0 TO N000-1), dic_1(0 TO t_max, 0 TO N000-1) !encoder 辞書
!
LET blkfull=255 ! block size max.(~~255)
LET bitfull=12 ! LZW bits max.(~~ 12)
DIM dic$(0 TO 2^bitfull) ! decoder 辞書、収納は、新規の登録番号最大まで。
!
!------------------- テスト原画の作成 -----------------------------------
LET Xw=4
LET Yw=3
MAT m=ZER(Yw,Xw)
MAT READ m
!MAT m=BVAL("03",16)*CON(Yw,Xw)
! 4色(2bits) 横:4 縦:3 の、テスト・パターン
DATA 0,1,2,3
DATA 0,1,2,3
DATA 0,1,2,3
!
PRINT "******************* 原画パターン"; Xw;"x";Yw
FOR j=1 TO Yw
LET ww$=""
FOR i=1 TO Xw
LET ww$=ww$& right$("0"& BSTR$(m(j,i),16),2)& " "
NEXT i
PRINT ww$
NEXT j
!
CALL picture_data ! 上記パターンを 実際に、Encode する。原画→ LZW$
CALL decomp_data ! 上のEncode 出力を 実際に、Decode する。LZW$→ 原画
!------------------- 原画から、画像データ LZW$ の作成。------------------
!画像配列 m(1~Yw,1~Xw) !! 注意 x,y の順 mat read m(y,x)
SUB inppix !! ask pixel array(x0,y0) m(x,y)
LET lx=lx+1
IF Xw< lx THEN
LET lx=1
LET ly=ly+1
END IF
IF ly<=Yw THEN LET bx=m(ly,lx) ! data on bx
END SUB
SUB picture_data
PRINT "******************* 圧縮( LZW エンコード )"
LET LZW$=CHR$(obits0)
CALL prthex(CHR$(obits0),"最小データービット長") !予約登録番号最大のビット長
!---
CALL LZW_encoder
CALL
outcode !flush
last chained dic.number on ax
LET ax=N000+1
CALL outcode !code end
CALL out_flush
!---
LET LZW$=LZW$& CHR$(0) !block end
CALL prthex(CHR$(0),"block size") !モニター
END SUB
SUB LZW_encoder
LET lx=1 -1 !画像配列 start pointer
LET ly=1
CALL inppix !data on bx
LET pdata$="" !clear output byte buffer
LET oacc$="" !clear output bit buffer
LET owidth=obits0+1 !starting bit width
DO
LET ax=N000 !reset code
CALL outcode
MAT dic_0=ZER !clear dic.number
MAT dic_1=ZER !clear dic.chain
LET
thead=1 !reset
make_table pointer
LET dicnum=N000+2 !reset new dic.number
LET owidth=obits0+1 !starting bit width
DO
LET
di=0 !top
table
LET
dic_0(di,bx)=bx !bx as reserved
dic.number
DO
LET
ax=dic_0(di,bx) !---latch last chained dic.number
IF
dic_1(di,bx)>0 THEN LET di=dic_1(di,bx) ELSE CALL make_table
CALL
inppix !
next bx
IF Yw< ly THEN EXIT SUB
LOOP UNTIL dic_0(di,bx)=0 !---until no dic.number
LET dic_0(di,bx)=dicnum ! new dic.number, bx as tail& next top
CALL
outcode !
write ax, last chained dic.number
LET owidth=LEN( BSTR$(dicnum,2) ) ! remake owidth
LET dicnum=dicnum+1
LOOP UNTIL dicnum>2^bitfull-1 OR thead>t_max !bits full or dic.full
LOOP
END SUB
SUB make_table
LET dic_1(di,bx)=thead !chained table pointer
LET di=thead !new table head
LET thead=thead+1
END SUB
SUB outcode
LET oacc$=right$("00000000000"& BSTR$(ax,2),owidth)& oacc$
DO WHILE LEN(oacc$)>=8
LET pdata$=pdata$& CHR$(BVAL(right$(oacc$,8),2))
LET oacc$=oacc$(1:LEN(oacc$)-8)
IF blkfull=LEN(pdata$) THEN CALL bw_sub
LOOP
END SUB
SUB bw_sub
LET LZW$=LZW$& CHR$(LEN(pdata$))& pdata$
CALL prthex( CHR$(LEN(pdata$)),"block size") !モニター
CALL prthex( pdata$,"LZW compression bit stream") !モニター
LET pdata$=""
END SUB
SUB out_flush
IF oacc$<>"" THEN LET pdata$=pdata$& CHR$(BVAL(oacc$,2) )
LET oacc$=""
IF pdata$>"" THEN CALL bw_sub
END SUB
!---------------- モニター共通パーツ
SUB prthex(d$,w$)
LET ww$=""
FOR ii=1 TO LEN(d$)
LET ww$=ww$& right$("0"& BSTR$(ORD(d$(ii:ii)),16),2)& " "
NEXT ii
IF w$>"" THEN LET ww$=ww$& "; "& w$
PRINT ww$
END SUB
!------------------- 画像データ LZW$ から、原画へ戻す。------------------
SUB decomp_data
PRINT "******************* 復元( LZW デコード )"
LET obits0=ORD(LZW$(1:1))
CALL prthex(CHR$(obits0),"最小データービット長") !モニター
LET N000=2^obits0
LET
li=2
!start input pointer
LET
blkend=0
!clear input block pointer
LET
iacc$=""
!clear input bit buffer
LET
pdata$="" !clear
output byte buffer
CALL LZW_decoder
FOR i=1 TO LEN(pdata$) STEP Xw
CALL prthex(pdata$(i:i+Xw-1),"") !モニター
NEXT i
!--- check block_end
CALL prthex( LZW$(li:li),"block size") !モニター
END SUB
SUB LZW_decoder
DO
LET
dicnum=N000+2-1
!start dic.number-1
DO
LET iwidth=LEN( BSTR$(dicnum,2) ) !remake iwidth
IF bitfull< iwidth THEN LET iwidth=bitfull !to handle BAD encode
LET dicnum=dicnum+1
CALL
inpcode
!data on bx
IF bx=-1 OR bx=N000+1 THEN
EXIT SUB
ELSEIF bx=N000 THEN
EXIT DO
ELSE
IF bx< N000 THEN
LET dic$(dicnum)=CHR$(bx)
ELSE
LET dic$(dicnum)=dic$(bx)
LET dic$(dicnum)=dic$(dicnum)& dic$(bx+1)(1:1)
END IF
LET pdata$=pdata$& dic$(dicnum)
END IF
LOOP
LOOP
END SUB
SUB inpcode
LET bx=-1
DO WHILE LEN(iacc$)< iwidth
IF blkend<=li THEN
LET blksize=ORD(LZW$(li:li))
CALL prthex(CHR$(blksize),"block size") !モニター
IF blksize=0 THEN EXIT SUB
LET li=li+1
LET blkend=li+blksize
END IF
LET iacc$=right$("0000000"& BSTR$(ORD(LZW$(li:li)),2),8)& iacc$
LET li=li+1
LOOP
LET bx=BVAL(right$(iacc$,iwidth),2)
LET iacc$=iacc$(1:LEN(iacc$)-iwidth)
END SUB
!●数列によるアプローチ
!例. n=9の場合
! 1+2+3+4+5+ … +9 4で条件を満たさない
! 2+3+4+5+ … +9 4で条件を満たす
! 3+4+5+ … +9 5で条件を満たさない
! 4+5+ … +9 5で条件を満たす
! :
! 7+8+9 8で条件を満たさない
! 8+9 9で条件を満たさない
!高々nまでの和を求めて、元の数に等しくなるか確認する
LET n=9 !求める数
FOR a=1 TO n-1 !初項
LET s=0
FOR m=a TO n !高々nまでの和
LET s=s+m
IF s=n THEN !等しいなら
FOR k=a TO m !結果を表示する
PRINT "+";k;
NEXT k
PRINT "=";s !検算
END IF
IF s>=n THEN EXIT FOR !これ以降は条件を満たさないので、次へ
NEXT m
NEXT a
!●別解
LET n=9 !求める数
FOR a=1 TO n-1 !初項
LET d=1 !初項a、公差dの等差数列の第m項までの和
FOR m=1 TO n !高々n項まで
LET s=m*(2*a+(m-1)*d)/2 !和の公式
IF s=n THEN !等しいなら
FOR k=1 TO m !結果を表示する
PRINT "+";a+(k-1)*d; !一般項の公式
NEXT k
PRINT "=";s !検算
END IF
IF s>=n THEN EXIT FOR !これ以降は条件を満たさないので、次へ
NEXT m
NEXT a
!●2次方程式の解によるアプローチ
!例. n=9の場合
! 1+2+3+4+5+ … +t a=1、t=3.772…
! 1+ 2+3+4+5+ … +t a=2、t=4
! 1+2+ 3+4+5+ … +t a=3、t=4.424…
! 1+2+3+ 4+5+ … +t a=4、t=5
! :
! 1+2+3+4+5+6+ 7+8+t a=7、t=7.262…
! 1+2+3+4+5+6+7+ 8+t a=8、t=8.116…
!1〜kまでの和はk*(k+1)/2より、a,a+1,…,tまでの和は、t*(t+1)/2-(a-1)*a/2となる。
!これがnと等しい。aを固定すると、2次方程式 t^2+t-(2*n+(a-1)*a)=0 の解となる。
LET n=9 !求める数
FOR a=1 TO n-1 !aを固定する
LET D=1*1-4*1*(-(2*n+(a-1)*a)) !判別式
IF D>=0 THEN !実数解なら
LET t=(-1+SQR(D))/2 !1つ目の解
!PRINT a;t !debug
IF t>0 AND INT(t)=t THEN !tは自然数なら
FOR k=a TO t !結果を表示する
PRINT "+";k;
NEXT k
PRINT "=";t*(t+1)/2-(a-1)*a/2 !検算
END IF
LET t=(-1-SQR(D))/2 !2つ目の解 ※こちらが条件を満たすことはない
!PRINT a;t !debug
IF t>0 AND INT(t)=t THEN
FOR k=a TO t
PRINT "+";k;
NEXT k
PRINT "=";t*(t+1)/2-(a-1)*a/2
END IF
END IF
NEXT a
!●約数によるアプローチ
!例. n=9の場合
! 約数は1,3,9。1を除く奇数の約数に着目する。
! たとえば、nが3で割り切れることより、3等分できる。すなわち、n=9=3+3+3となる。
! 3のとき、n=3+(3)+3=(3-1)+3+(3+1)=2+3+4 と真ん中の3を基準に、変形する。
! 9のとき、n=1+1+1+1+(1)+1+1+1+1
! =(1-4)+(1-3)+(1-2)+(1-1)+1+(1+1)+(1+2)+(1+3)+(1+4)
! =(-3)+(-2)+(-1)+0+1+2+3+4+5
! =4+5
LET n=9 !求める数
FOR f=2 TO n !1を除く約数をみつける
IF MOD(n,f)=0 THEN
IF MOD(f,2)=1 THEN !奇数に着目する
LET c=INT(f/2)+1 !真ん中の位置を得て、それを基準に変形する
LET s=0 !相殺部分の範囲を得る
FOR i=1 TO f
LET k=n/f + (i-c) !f等分±1,2,3,…
!PRINT i;k !debug
LET s=s+k
IF s>0 THEN PRINT "+";k;
NEXT i
PRINT "=";s !検算
END IF
END IF
NEXT f
!●別解 奇数が連続する2つの自然数の和で表される
!例. n=9の場合
! 約数は1,3,9。1を除く奇数の約数に着目する。
! たとえば、nが3で割り切れることより、3は倍数となる。すなわち、n=3*3=3+3+3。
! この3を連続する2つの自然数の和で表すと、3=1+2。
! 残りの3も、これを基準に1−1,2,3,…、2+1,2,3,…の和で表す。
! 3のとき、n=3*3=3+3+3=(1+2)+(0+3)+(-1+4)=-1+0+1+2+3+4=2+3+4 と変形する。
! 9のとき、n=9*1=9=(4+5)
LET n=9 !求める数
FOR f=2 TO n !約数をみつける
IF MOD(n,f)=0 THEN
IF MOD(f,2)=1 THEN !奇数に着目する
LET c=(f-1)/2 !連続する2つの自然数c,c+1の和にする
LET s=0 !相殺部分の範囲を得る
FOR k=c-n/f+1 TO c+n/f !変形した式を計算する
!PRINT k !debug
LET s=s+k
IF s>0 THEN PRINT "+";k;
NEXT k
PRINT "=";s !検算
END IF
END IF
NEXT f
END
!Page-2 の始め
!------------------- 画像データ LZW$ から、原画を見る。------------------
SUB decomp_data
PRINT "******************* 復元( LZW デコード )"
LET obits0=ORD(LZW$(1:1))
CALL prthex(CHR$(obits0),"最小データービット長") !モニター
LET N000=2^obits0
LET
li=2
!start input pointer
LET
blkend=0
!clear input block pointer
LET
iacc$=""
!clear input bit buffer
LET
pdata$="" !clear
output byte buffer
CALL LZW_decoder
PRINT "Last_code LEN(LZW$) LEN(pdata$)=";bx;LEN(LZW$);LEN(pdata$) !モニター
!---
IF tmod=3 THEN MAT m3=m
LET ii=1
IF interl=0 THEN
CALL intlace( 0, 1) ! start_raster, step !---NO interlace
ELSE
CALL intlace( 0, 8) ! start_raster, step !---0~7step8
WAIT DELAY .5
CALL intlace( 4, 8) ! start_raster, step !---4~7step8
WAIT DELAY .5
CALL intlace( 2, 4) ! start_raster, step !---2~3step4
WAIT DELAY .5
CALL intlace( 1, 2) ! start_raster, step !---1~1step2
END IF
IF tmod=2 THEN MAT m=ncp(256)*CON ! 256= システム背景色
IF tmod=3 THEN MAT m=m3
!--- check block_end
CALL prthex( LZW$(li:li),"block size") !モニター
PRINT "******************* 復元終り"
END SUB
SUB intlace( ss, stp)
FOR j=Yp0 TO Yp0+Ypw-1
IF MOD(j-Yp0, stp) >=ss THEN
IF MOD(j-Yp0, stp) >ss THEN LET ii=ii-Xpw
FOR i=Xp0 TO Xp0+Xpw-1
WHEN EXCEPTION IN
LET col=ORD(pdata$(ii:ii))
IF t_on<>1 OR tcol<>col THEN LET m(i,j)=ncp(col)
LET ii=ii+1
USE
END WHEN
NEXT i
END IF
NEXT j
MAT PLOT CELLS,IN 0,0; Xsw-1,Ysw-1 :m
END SUB
!-------------
SUB LZW_decoder
DO
LET
dicnum=N000+2-1
!start dic.number-1
DO
LET iwidth=LEN( BSTR$(dicnum,2) ) !remake iwidth
IF bitfull< iwidth THEN LET iwidth=bitfull !to handle BAD file
LET dicnum=dicnum+1
CALL
inpcode
!data on bx
IF bx=-1 OR bx=N000+1 THEN
EXIT SUB
ELSEIF bx=N000 THEN
EXIT DO
ELSE
IF bx< N000 THEN
LET dic$(dicnum)=CHR$(bx)
ELSE
LET dic$(dicnum)=dic$(bx)
LET dic$(dicnum)=dic$(dicnum)& dic$(bx+1)(1:1)
END IF
LET pdata$=pdata$& dic$(dicnum)
END IF
LOOP
LOOP
END SUB
SUB inpcode
LET bx=-1
DO WHILE LEN(iacc$)< iwidth
IF blkend<=li THEN
LET blksize=ORD(LZW$(li:li))
CALL prthex(CHR$(blksize),"block size") !モニター
IF blksize=0 THEN EXIT SUB
LET li=li+1
LET blkend=li+blksize
END IF
LET iacc$=right$("0000000"& BSTR$(ORD(LZW$(li:li)),2),8)& iacc$
LET li=li+1
LOOP
LET bx=BVAL(right$(iacc$,iwidth),2)
LET iacc$=iacc$(1:LEN(iacc$)-iwidth)
END SUB
SUB prthex(d$,w$)
LET ww$=""
FOR ii=1 TO LEN(d$)
LET ww$=ww$& right$("0"& BSTR$(ORD(d$(ii:ii)),16),2)& " "
NEXT ii
IF w$>"" THEN LET ww$=ww$& "; "& w$
PRINT ww$
END SUB
! GIF ファイルの解析ツール Ver.2(画像付)
!-------
! リスト左端アドレスを5桁にした。リスト注釈を大幅修正。復元画像も、
! 表示する様にした。IE6 は、スクリーン背景色を無視して、ブラウザ背景
! のみを、代用するようなので、GIF仕様から外れるが、それに合せた。
! Disposal Method 0,1,2,3 、インタレース画像などが、モニター出来る。
!
OPTION CHARACTER BYTE
LET bitfull=12 ! LZW max.bits (~~ 12)
DIM dic$(0 TO 2^bitfull) ! decoder 辞書
!
FILE GETNAME file$, "gif"
IF file$="" THEN
PRINT "入力ファイル名が、ありません。"
STOP
END IF
!
PRINT "入力ファイル:"& file$
OPEN #1: NAME file$, ACCESS INPUT
PRINT "---------"
SET COLOR mode "native"
DIM ncp(0 TO 256) ! native color palette
LET ncp(256)=BVAL("eeeedd",16) ! 256= システム背景色 BGR
SET AREA COLOR ncp(256)
PLOT AREA: 0,0;1,0;1,1;0,1
CALL gif_head
LET i=MAX( Xsw,Ysw )
SET WINDOW -.1*i,1.1*i, 1.1*i,-.1*i
SET LINE STYLE 3
PLOT LINES:-1,-1;Xsw+.5,-1;Xsw+.5,Ysw+.5;-1,Ysw+.5;-1,-1
DIM m(0 TO Xsw-1,0 TO Ysw-1), m3(0 TO Xsw-1,0 TO Ysw-1)
MAT m=ncp(256)*CON
DO
CALL blocks_main
LOOP UNTIL b1$=CHR$(BVAL("3B",16))
PRINT "GIF 終端ブロック"
CALL dump(b1$,2,"block label")
PRINT "---------"
CLOSE #1
!----
SUB gif_head
LET h$=""
CALL readb( h$,13 )
IF h$(1:3)="GIF" THEN PRINT "GIF ヘッダー" ELSE CALL error
LET Xsw= ORD(h$( 8: 8))*256+ORD(h$(7:7))
LET Ysw= ORD(h$(10:10))*256+ORD(h$(9:9))
LET sflg=ORD(h$(11:11)) ! スクリーン情報のフラグ
LET BGco=ORD(h$(12:12))
LET aspect=ORD(h$(13:13))
LET b$=right$("0000000"& BSTR$(sflg,2) ,8)
LET colpix=2^(BVAL(b$(2:4),2)+1)
LET compal=2^(BVAL(b$(6:8),2)+1)
CALL dump(h$( 1: 6),6,"Asc") ! GIF識別文字
CALL dump(h$( 7: 8),2,"screen X_width= "& STR$(Xsw))
CALL dump(h$( 9:10),2,"screen Y_width= "& STR$(Ysw))
CALL dump(h$(11:11),2,"flags= "& b$ )
PRINT TAB(13);b$(1:1);":common_palette on=1/off=0"
PRINT TAB(11);b$(2:4);":colors/pixel 2^(";b$(2:4);"b+1)= ";STR$(colpix)
PRINT TAB(13);b$(5:5);":sort on=1/off=0 パレットの、重要度 色順ソート"
PRINT TAB(11);b$(6:8);":common_palette colors 2^(";b$(6:8);"b+1)= ";STR$(compal)
CALL dump(h$(12:12),2,"back_ground color= "& STR$(BGco))
IF aspect=0 THEN LET b$=".." ELSE LET b$=STR$(aspect)
CALL dump(h$(13:13),2,"アスペクト比 H:V=, 0 は 1:1 その他("& b$& "+15):64" )
CALL palette("common_パレット", c_p$, sflg)
END SUB
!----
SUB blocks_main
LET b1$=""
CALL readb( b1$, 1)
IF b1$=CHR$(BVAL("21",16)) THEN !追加データ・ブロック
CALL option_block
ELSEIF b1$=CHR$(BVAL("2C",16)) THEN !画像ブロック
CALL picture_block
ELSEIF b1$=CHR$(BVAL("3B",16)) THEN !GIF 終端ブロック
ELSE
CALL error
END IF
END SUB
!---追加データ・ブロック。
SUB option_block
PRINT "追加データ・ブロック"
CALL readb( b1$,1) ! w9$= readb_last_byte
IF w9$=CHR$(BVAL("F9",16)) THEN
LET im$=b1$
CALL dump(im$,2,"イメージコントロール・ブロック")
CALL blocks(im$,0,"",1) ! non print (data, byte/行, 注釈, 要求blocks)
LET iflg=ORD(im$(4:4)) ! フラグ
LET imtm=ORD(im$(6:6))*256+ORD(im$(5:5))
LET tcol=ORD(im$(7:7))
LET b$=right$("0000000"& BSTR$(iflg,2),8)
LET t_on=VAL(b$(8:8))
LET tmod=BVAL(b$(4:6),2)
CALL dump(im$(4:4),2,"flags= "& b$ )
PRINT TAB(11);b$(1:3);":blank"
PRINT TAB(11);b$(4:6);":"
PRINT TAB(15);"000= 描画後、そのまま、次の背景へ渡す"
PRINT TAB(15);"001= 描画後、そのまま、次の背景へ渡す"
PRINT TAB(15);"010= 描画後、back_ground color と取替、次の背景へ渡す"
PRINT TAB(15);"011= 描画後、描画前の画像を、次の背景へ渡す"
PRINT TAB(13);b$(7:7);":user click on=1/off=0"
PRINT TAB(13);b$(8:8);":透明色のスイッチ on=1/off=0"
CALL dump(im$(5:6),2,"フレーム表示時間= "& STR$(imtm)& " x10ms" )
CALL dump(im$(7:7),2,"透明色= "& STR$(tcol) )
CALL blocks(im$,16,"",999) ! (data, byte/行, 注釈, 要求blocks)
ELSEIF w9$=CHR$(BVAL("FE",16)) THEN
LET co$=b1$
CALL dump(co$,2,"コメント・ブロック")
CALL blocks(co$,8,"Asc",999) ! (data, byte/行, 注釈, 要求blocks)
ELSEIF w9$=CHR$(BVAL("FF",16)) THEN
LET ap$=b1$
CALL dump(ap$,2,"アプリケーション・ブロック")
CALL blocks(ap$,8,"Asc",1) ! (data, byte/行, 注釈, 要求blocks)
IF ap$(4:11)="NETSCAPE" THEN
CALL blocks(ap$,0,"",1) ! non print (data, byte/行, 注釈, 要求blocks)
CALL dump(ap$(16:16),2,"extension code= 01~07 next data type")
IF MOD(ORD(ap$(16:16)),8)=1 THEN
LET rept=ORD(ap$(18:18))*256+ORD(ap$(17:17))
CALL
dump(ap$(17:18),2,"繰返し回数= "& STR$(rept)& " (0=endless)")
ELSE
CALL
dump(ap$(17:LEN(ap$)),2,"02= 32bit buffering size, 03~07= ?")
END IF
END IF
CALL blocks(ap$,8,"Asc",999) ! (data, byte/行, 注釈, 要求blocks)
ELSEIF w9$=CHR$(BVAL("01",16)) THEN
LET tx$=b1$
CALL dump(tx$,2,"テキスト・イメージ・ブロック")
CALL blocks(d$,8,"Asc",999) ! (data, byte/行, 注釈, 要求blocks)
ELSE
CALL error
END IF
END SUB
!-------
SUB blocks(d$,m,t$,n) ! d$=data, m=byte/行, t$=注釈, n=要求blocks
FOR n=1 TO n
CALL
readb(d$,1)
! w9$= readb_last_byte ! =block Size
CALL dump(w9$,1,"block size")
IF w9$=CHR$(0) THEN EXIT SUB ! block End
LET s=LEN(d$)
CALL readb(d$,ORD(w9$)) ! block data
IF 0< m THEN CALL dump(d$(s+1:LEN(d$)),m,t$)
NEXT n
END SUB
SUB readb(d$,cx) !cx=bytes size
FOR i=1 TO cx
CHARACTER INPUT #1,IF MISSING THEN EXIT FOR :w9$
LET d$=d$& w9$
NEXT i
IF i<=cx THEN CALL error
END SUB
SUB dump(d$,m,t$) ! t$="comment" →;comment t$="Asc" →;"ascii.dump"
FOR j=1 TO LEN(d$) STEP m
LET ww$=right$("0000"& BSTR$(adr,16),5)& " "
FOR i=j TO MIN(j+m-1, LEN(d$))
LET ww$=ww$& " "& right$("0"& BSTR$( ORD(d$(i:i)),16),2)
LET adr=adr+1
NEXT i
IF t$>"" THEN
LET ww$=ww$& REPEAT$(" ",6+3*m-LEN(ww$))
IF t$="Asc"
THEN !
ascii.dump
LET ww$=ww$& " ;"""
FOR i=j TO MIN(j+m-1, LEN(d$))
IF " "<=d$(i:i) THEN LET ww$=ww$& d$(i:i) ELSE LET ww$=ww$&
"."
NEXT i
LET ww$=ww$& """"
ELSE
IF
m=3 THEN LET ww$=ww$& " ;"& STR$(IP(j/3)) ! パレット色番号
IF
j=1 THEN LET ww$=ww$& " ;"&
t$ !
comment
END IF
END IF
PRINT ww$ ! 行単位、テキスト画面のピカつき減少、高速。
NEXT j
END SUB
!-------
SUB picture_block
PRINT "画像ブロック"
LET pi$=b1$
CALL readb( pi$,9)
CALL dump(pi$(1:1),2,"block label")
LET Xp0=ORD(pi$(3:3))*256+ORD(pi$(2:2))
LET Yp0=ORD(pi$(5:5))*256+ORD(pi$(4:4))
LET Xpw=ORD(pi$(7:7))*256+ORD(pi$(6:6))
LET Ypw=ORD(pi$(9:9))*256+ORD(pi$(8:8))
CALL dump(pi$(2:3),2,"picture.X0_position left= "& STR$(Xp0))
CALL dump(pi$(4:5),2,"picture.Y0_position top= "& STR$(Yp0))
CALL dump(pi$(6:7),2,"picture.X_width= "& STR$(Xpw))
CALL dump(pi$(8:9),2,"picture.Y_width= "& STR$(Ypw))
LET pflg=ORD(pi$(10:10)) ! 画像情報のフラグ
LET b$=right$("0000000"& BSTR$(pflg,2),8)
CALL dump(pi$(10:10),2,"flags= "& b$ )
LET interl=VAL(b$(2:2))
LET pripal=2^(BVAL(b$(6:8),2)+1)
PRINT TAB(13);b$(1:1);":private_palette on=1/off=0"
PRINT TAB(13);b$(2:2);":interlace on=1/off=0, 1~step8 5~step8 3~step4 2~step2"
PRINT TAB(13);b$(3:3);":sort on=1/off=0 パレットの、重要度 色順ソート"
PRINT TAB(12);b$(4:5);":blank"
PRINT TAB(11);b$(6:8);":private_palette colors 2^(";b$(6:8);"b+1)= ";STR$(pripal)
CALL palette("private_パレット", p_p$, pflg)
!---
PRINT "画像データ"
LET LZW$=""
CALL readb( LZW$,1)
CALL dump(LZW$,1,"最小データ・ビット長")
!--- LZW データ(size:data, size:data, … 0 )
CALL blocks(LZW$,16,"",9999) ! (data, byte/行, 注釈, 要求blocks)
CALL decomp_data
END SUB
SUB palette(n$, p$, pf)
PRINT n$;
LET p$=""
IF IP(pf/128)>0 THEN ! pf AND 0x80
PRINT
CALL readb(p$, 3*2^(MOD(pf,8)+1)) ! pf AND 0x07
CALL dump(p$,3,"R G B")
CALL palette10(n$, p$, pf)
ELSE
LET ww$=" 無し。"
IF n$(1:1)="p" AND c_p$>"" THEN
LET ww$=ww$& "→ common_パレット 使用。"
IF bk_p$(1:1)<>"c" THEN CALL palette10("common", c_p$, sflg)
END IF
PRINT ww$
END IF
END SUB
SUB palette10(n$, p$, pf)
FOR i=1 TO 3*2^(MOD(pf,8)+1) STEP 3
LET ncp(IP(i/3))= ORD(p$(i:i))+256*ORD(p$(i+1:i+1))+65536*ORD(p$(i+2:i+2))
NEXT i
LET bk_p$=n$
END SUB
SUB error
beep
PRINT "File Error Stop"
STOP
END SUB
本年度大学入試プログラミングの問題
慶応・環境情報
フィボナッチ数列の最初の20項を出力する問題で
模範解答とは異なる
150 let b=a-b
160 let a=a+b
としても、正しい出力が得られます。
問題文には、「もっとも適切なものを選び・・・」と
書かれているので、これは不正解なのでしょうか?
みなさまのご意見をお聞かせください。
数研、旺文社の正解は、次です。
100 LET a=1
110 LET b=0
120 LET n=0
130 IF n=20 THEN GOTO 190
140 LET n=n+1
150 LET b=a+b
160 LET a=b-a
170 PRINT b
180 GOTO 130
190 END
100 LET a=1 !古いb
110 LET b=0 !A[0]
120 LET n=0 !項
130 IF n=20 THEN GOTO 190 !第20項まで
140 LET n=n+1
150 LET b=a+b !=a[n-2]+a[n-1]=A[n](=古いb+b)
160 LET a=b-a !a=b-a=A[n]-a[n-1]=a[n-2]=古いb
170 PRINT n; a; b !第n項を表示する
180 GOTO 130
190 END
!ユークリッドの互除法で、4181と6765との最大公約数を求める
LET a=4181 !※a< b
LET b=6765
PRINT b
DO WHILE a<>b !a=bなら終了
IF a>b THEN
LET a=a-b !「a-bとbとの最大公約数を求める」に置き換える
PRINT b !trace
ELSE
LET b=b-a
PRINT a !trace
END IF
LOOP
PRINT a !最大公約数
!その2 剰余を使った場合
LET a=4181 !※bを出力するためには、a< bとする
LET b=6765
DO UNTIL b=0
LET t=b
LET b=MOD(a,b)
LET a=t
PRINT a !trace
LOOP
PRINT a !最大公約数
END
100 LET a=1 !奇数の項: a[-1]
110 LET b=0 !偶数の項: a[0]
120 LET n=0 !組
130 IF n=10 THEN GOTO 190 !10組まで
140 LET n=n+1
150 LET a=a+b !=a[k-1]+a[k]=a[k+1]
160 LET b=b+a !=b+(a+b)=2*b+a=2*a[k]+a[k-1]=a[k]+(a[k-1]+a[k])=a[k]+a[k+1]=a[k+2]
170 PRINT a; b !2数
180 GOTO 130
190 END
SQR関数は,偏角が−π/2より大でπ/2以下である平方根を返すようになっています。
次のように平方根関数sqrtを定義すれば,偏角が0以上π未満であるようになります。
FUNCTION sqrt(x)
LET x=SQR(x)
IF x<>0 AND ARG(x)<0 THEN
LET x=x*(-1)
END IF
LET sqrt=x
END FUNCTION
! 以下,使用例
LET x=COMPLEX(-1/2,-SQR(3)/2)
PRINT SQR(x),sqrt(x)
END
複素関数の詳細は,ヘルプの複素関数のページを見てください。
(1) FACT(x)を2進モード,複素数モードで実行した場合、xが小数のとき例外とならず誤った値を返す。
100 OPTION ARITHMETIC NATIVE
110 FOR x=-1 TO 4
120 WHEN EXCEPTION IN
130 PRINT x;FACT(x) ! 整数では問題ない
140 USE
150 END WHEN
160 NEXT x
170 PRINT
180 FOR x=-1 TO 4.0001 STEP 0.1
190 WHEN EXCEPTION IN
200 PRINT x;FACT(x) ! x<-0.5では例外が発生
210 USE
220 END WHEN
230 NEXT x
240 END
上記プログラムを10進15桁,1000桁,有理数の各モードで実行した場合、xが小数のときは例外が発生する。
(2) PERM(n,r);COMB(n,r)を2進モード,複素数モードで実行した場合、rが小数のとき例外とならずrを整数に丸めて得た値を返す。
400 OPTION ARITHMETIC NATIVE
410 LET n=6
420 FOR r=-2 TO 3.0001 STEP 0.1
430 WHEN EXCEPTION IN
440 PRINT n;r;" ---> ";PERM(n,r);COMB(n,r) ! r<-0.5では例外が発生
450 USE
460 END WHEN
470 NEXT r
480 END
上記プログラムを10進15桁,1000桁,有理数の各モードで実行した場合、rが小数のときは例外が発生する。
(3) PERM(n,r),COMB(n,r)でnが負数,小数のとき例外とならず誤った値を返す。
600 LET r=3
610 FOR n=-4 TO 5 STEP 0.2
620 WHEN EXCEPTION IN
630 PRINT n;r;" ===> ";PERM(n,r);COMB(n,r)
640 USE
650 END WHEN
660 NEXT n
670 END
!クルスカル・カウント(Kruskal count)
LET N=52 !カードの枚数
LET mk$="SCHD" !カードのマーク
LET nm$="A234567890JQK" !カードの番号
DEF s2n(s)=MOD(s-1,13)+1 !連番をカードの番号へ
DEF s2m(s)=INT((s-1)/13)+1 !連番をカードのマークへ
DIM c(N) !カードの並び
SUB card_initialize(c(),N) !カードを整列する
FOR i=1 TO N
LET c(i)=i
!!!PRINT i;s2m(i);s2n(i)
NEXT i
END SUB
RANDOMIZE
SUB shuffle_randomize(c(),N) !ランダムにシャッフルする
FOR i=N TO 2 STEP -1
LET j=INT(RND*(i-1))+1 !1〜i-1
swap c(i),c(j)
NEXT i
END SUB
!------------------------------ ここまでがサブルーチン
CALL card_initialize(c,N)
CALL shuffle_randomize(c,N)
MAT PRINT c;
FOR r=1 TO 10 !好きな数字
LET p=r !その数字の枚数分、トランプを上から順に表向きにして机の上に重ねて配る(順番を崩さないため)
DO WHILE p<=N !手持ちのトランプの残りがなければ、終了。
PRINT c(p); !表向きの一番上のトランプの数字
LET t=s2n(c(p)) !1〜13
IF t>10 THEN LET t=5 !絵札はすべて5とする
LET p=p+t !次へ
LOOP
PRINT
NEXT r !机の上の表向きのトランプを全て取り上げて裏向きにし、手持ちのトランプの上に戻す
END
!n=13の場合
!0,1,2,3,4,5,6,7,8,9,10,11,12,13より、「1」の数は6個となる。
!∴f(13)=6
OPTION ARITHMETIC NATIVE
LET fn=0 !1の数
FOR n=0 TO 2^31-1 !範囲
LET t=n !0〜nを表現する
DO WHILE t>0 !各桁が1の数をかぞえる
IF MOD(t,10)=1 THEN LET fn=fn+1
LET t=INT(t/10)
LOOP
IF fn=n THEN PRINT "f(";n;")=";fn !f(n)=nのなら
NEXT n
END
OPTION ARITHMETIC NATIVE
LET fn=0 !1の数
FOR k=1 TO 12 !範囲
LET n=10^k-1 !9,99,999,9999,…
PRINT "f(";n;")=";
FOR i=INT(n/10)+1 TO n !0〜nを表現する
LET t=i !各桁の1の数をかぞえる
DO WHILE t>0
IF MOD(t,10)=1 THEN LET fn=fn+1
LET t=INT(t/10)
LOOP
NEXT i
PRINT fn !結果を表示する
NEXT k
END
OPTION ARITHMETIC NATIVE
DECLARE FUNCTION change
DIM sum1(2 TO 10),max_n(2 TO 10)
MAT sum1=ZER
PRINT USING "##### ############(=>#########)":"p進法","f(n)=n最大値","10進数"
FOR n=1 TO 7^7
FOR p=2 TO 7 ! p=8以上は個々に計算しないと時間がかかる
LET x=n
DO
IF MOD(x,p)=1 THEN LET sum1(p)=sum1(p)+1
LET x=INT(x/p)
LOOP UNTIL x=0
IF sum1(p)=n THEN LET max_n(p)=n ! f(n)=n
NEXT p
NEXT n
FOR p=2 TO 10
PRINT USING " ## ########### (=##########)":p,change(max_n(p),p),max_n(p)
NEXT p
!
FUNCTION change(x,p) ! 10進数をp進数に変換
LET s,k=0
DO
LET s=MOD(x,p)*10^k+s
LET k=k+1
LET x=INT(x/p)
LOOP UNTIL x=0
LET change=s
END FUNCTION
END
ヘルプの[操作][オプションメニュー][数値]によると、実際に計算される数値と表示される数値の精度に違いがあるようです。
例1では、2進モードでx1は19桁目までは 2.999999999999999555 の値を持ちますが通常表示では15桁に丸められ 3 と表示されます。
例2例3は「10進15桁モードでは数値式とその値を代入した変数とでは精度が異なる」ことに起因すると思われます。
たとえば次の小プログラムでも、10進モードでは a/7 と b は異なる値になります。
10 LET a=1
20 LET b=a/7
30 PRINT a/7 ; b
40 END
OPTION ARITHMETIC DECIMAL
!LET p=10 !例1
!LET n=1000
!LET p=5 !例2
!LET n=625
LET p=7 !例3
LET n=49
LET x1=LOG(n)/LOG(p) !整数部分が異なる
LET x2=INT(LOG(n)/LOG(p)) !
PRINT "LOG(n)/LOG(p) =";LOG(n)/LOG(p)
PRINT "x1 =";x1
PRINT "INT(LOG(n)/LOG(p)) =";INT(LOG(n)/LOG(p))
PRINT "INT(x1) =";INT(x1)
PRINT "x2 =";x2
PRINT
CALL binary(STR$(p),STR$(n))
PRINT
CALL thousand(STR$(p),STR$(n))
END
EXTERNAL SUB binary(p$,n$)
OPTION ARITHMETIC NATIVE
LET p=VAL(p$)
LET n=VAL(n$)
LET x1=LOG(n)/LOG(p) !整数部分が異なる
LET x2=INT(LOG(n)/LOG(p)) !
PRINT "LOG(n)/LOG(p) =";LOG(n)/LOG(p)
PRINT "x1 =";x1
PRINT "INT(LOG(n)/LOG(p)) =";INT(LOG(n)/LOG(p))
PRINT "INT(x1) =";INT(x1)
PRINT "x2 =";x2
END SUB
EXTERNAL SUB thousand(p$,n$)
OPTION ARITHMETIC DECIMAL_HIGH
LET p=VAL(p$)
LET n=VAL(n$)
LET x1=LOG(n)/LOG(p) !整数部分が異なる
LET x2=INT(LOG(n)/LOG(p)) !
PRINT "LOG(n)/LOG(p) =";LOG(n)/LOG(p)
PRINT "x1 =";x1
PRINT "INT(LOG(n)/LOG(p)) =";INT(LOG(n)/LOG(p))
PRINT "INT(x1) =";INT(x1)
PRINT "x2 =";x2
END SUB
LET STR1$="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" !p進法の数字
FUNCTION ExBSTR$(n,p) !非負の整数nをp進法で表記する
LET s$=""
DO
LET nn=INT(n/p)
LET t=n-nn*p !MOD(n,p)
LET s$=STR1$(t+1:t+1)&s$ !下の位から
LET n=nn
LOOP UNTIL n=0
LET ExBSTR$=s$
END FUNCTION
LET p=5 !進数
FOR n=1 TO p^p !自然数
LET x=INT(LOG(n)/LOG(p))+1 !桁数
LET x2=INT(LOG2(n)/LOG2(p))+1
LET x10=INT(LOG10(n)/LOG10(p))+1
LET k=g(n,p) !進数変換による
IF k<>x OR k<>x2 OR k<>x10 THEN PRINT n; STR$(p);"#";ExBSTR$(n,p), k; x; x2; x10
NEXT n
FUNCTION g(n,p) !自然数nのp進法での桁数 ※p^c=n
LET t=1
LET c=0 !桁数
DO
LET t=t*p
LET c=c+1
LOOP WHILE t<=n
LET g=c
END FUNCTION
END
!例 f(123)の場合
!100と23に分解する
! 3桁の数(最上位桁=1)
! 1xx形式の数 = k桁目に(23+1)=24、(k-1)〜1桁目にf(_99)=20
! 端数23
! f(23)
! ⇒
! 20と3に分解する
! 2桁の数(最上位桁=2)
! 1x形式の数 = k桁目に10^(2-1)=10、(k-1)〜1桁目にf(_9)=1
! 2x形式の数 = k〜1桁目にf(_9)=1
! 端数3
! f(3)
! ⇒
! 3と0に分解する
! 1桁の数(最上位桁=3)
! 1形式の数 = 1桁目に10^(1-1)=1、(1-1)桁目にf(_)=0
! 2形式の数 = 1桁目にf(_)=0
! 3形式の数 = 1桁目にf(_)=0
! 端数0
! f(0)=0
!∴(24+20) + (10+1 +1) + (1+0 +0 +0) +0 = 57
FUNCTION f(n$,p) !0〜nまでを列記したときの「1」の数 ※n$は非負のp進法の数値
local k,m,t$
IF ExBVAL(n$,p)=0 THEN
LET f=0
ELSE
LET k=LEN(n$) !桁数
LET m=VAL1(n$(1:1)) !最上位桁に着目する
LET t$=n$(2:LEN(n$)) !端数
!PRINT n;k;m;t$ !debug
IF m=1 THEN !(1xxx…x)の場合
LET w=ExBVAL(t$,p)+1
ELSE !(2xxx…x)、…、(9xxx…x)の場合
LET w=p^(k-1)
END IF
LET f=( w + f(REPEAT$(STR1$(p:p),k-1),p)*m ) + f(t$,p) !k桁 + f(端数)
END IF
END FUNCTION
LET STR1$="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" !p進法の数字
DEF VAL1(x$)=POS(STR1$,x$)-1
FUNCTION ExBVAL(n$,p) !n$を非負のp進法の数値とした値
LET s=0
FOR i=1 TO LEN(n$)
LET s=s*p+VAL1(n$(i:i))
NEXT i
LET ExBVAL=s
END FUNCTION
FUNCTION ExBSTR$(n,p) !非負の整数nをp進法で表記する
LET s$=""
DO
LET nn=INT(n/p)
LET t=n-nn*p !MOD(n,p)
LET s$=STR1$(t+1:t+1)&s$ !下の位から
LET n=nn
LOOP UNTIL n=0
LET ExBSTR$=s$
END FUNCTION
!------------------------------ ここまでがサブルーチン
PRINT f("1111111110",10) !10進法
PRINT ExBVAL("111110",6); f("111110",6) !6進法
LET p=4 !4進法
FOR n=0 TO p^p
LET w$=ExBSTR$(n,p)
IF f(w$,p)=n THEN PRINT "f(";n;")=";n, STR$(p);"#";w$
NEXT n
END
!2から30までの整数では、
! 2,3,4,5,5,7,6,6,7, 11,7,13,9,8,8,17,8,19,9, 10,13,23,9,10,15,9,11,29,10
!となる。
LET N=30 !2〜Nの範囲
DIM sf(N) !素因数の和
MAT sf=ZER
LET j=2 !素因数2
DO WHILE j<=N
FOR i=j TO N STEP j !2,4,6,8,…、4,8,12,16,…、8,16,24,32,…、… 倍数
LET sf(i)=sf(i)+2 !素因数を加算していく
NEXT i
LET j=j*2 !2,4,8,16,… べき乗
LOOP
FOR k=3 TO N STEP 2 !3以上の素因数
IF sf(k)=0 THEN !「エラトステネスのふるい」と同じで素因数となる
LET j=k
DO WHILE j<=N !高々SQR(N)まで
FOR i=j TO N STEP j !j*m、m=1,2,3,…
LET sf(i)=sf(i)+k
NEXT i
LET j=j*k !k^m、m=1,2,3,…
LOOP
END IF
NEXT k
FOR i=2 TO N !結果を表示する
PRINT i;":"; sf(i)
NEXT i
END
●「素因数分解(式を表示する)」を改修する場合
LET N=120 !正の整数
LET s=0 !素因数の和 <----- 追加
PRINT N;":"; !<----- 変更
LET x=N
LET f=2 !割る数
DO WHILE x>=f*f !SQR(N)≧f
LET xx=INT(x/f)
IF x-xx*f=0 THEN !割り切れれば
LET x=xx
PRINT f;"+"; !<----- 変更
LET s=s+f !<----- 追加
ELSE !割り切れなければ、次へ
LET f=f+1
END IF
LOOP
PRINT x;
LET s=s+x !<----- 追加
PRINT "="; s !結果を表示する <----- 追加
END
数値の NOT AND OR 、語頭 0x での16進数表記 → personal extension の希望です。
縁の下の計算機には、最終的な命令とデータ形式… のはずですが、
使用しないように努力する癖 がついて、振り返る時、学習テーマに 是か否か、
自分の身分で考える事ではないけれども、疑問からの提案です。
BASIC だから「このままでいい」の声も強く聞こえるが・・・
Windows限定ですが, http://hp.vector.co.jp/authors/VA008683/BitOp.htm
を使えば,
LET A = AND( B, BVAL("30",16) )
あるいは,
LET A = AND(B, BVAL"00110000",2))
と書くことが可能です。
これらの関数はFull BASICの命令だけで定義することも可能なので,
互換性を損なうことはありません。
PRINT numb$("ONE+TWO+FOUR")
PRINT numb$("-One-Two-Three")
PRINT numb$("Two+Seven")
PRINT numb$(" - one + two - seven + ten ")
PRINT numb$("- one+ two- seven+ ten ")
PRINT numb$(" -one +two -seven +ten ")
FUNCTION numb$(w$)
LET n=0
LET i=1
DO WHILE i<=LEN(w$)
LET p$=""
DO WHILE w$(i:i)="+" OR w$(i:i)="-" OR w$(i:i)=" "
LET p$=p$& w$(i:i)
LET i=i+1
LOOP
LET n$=""
DO WHILE w$(i:i)<>"+" AND w$(i:i)<>"-" AND w$(i:i)<>" "
LET n$=n$& w$(i:i)
LET i=i+1
LOOP UNTIL LEN(w$)< i
LET j=num(n$)
IF POS(p$,"-")<>0 THEN LET j=-j
LET n=n+j
LOOP
IF n< 0 THEN LET p$="-" ELSE LET p$=""
LET numb$= p$& num$(ABS(n))
END FUNCTION
OPTION ARITHMETIC NATIVE
DIM n0(0 TO 9),nn(0 TO 9)
MAT READ n0
DATA 0,1,2,3,4,5,6,7,8,9
CALL perm(n0,0)
PRINT "終了"
SUB perm(n0(),j)
local i
IF j<=9 THEN
FOR i=0 TO 9-j
LET nn(j)=n0(i)
swap n0(i),n0(9-j)
CALL perm(n0,j+1)
swap n0(i),n0(9-j)
NEXT i
ELSE
CALL check
END IF
END SUB
SUB check
!MAT PRINT USING REPEAT$("# ",10):nn
LET E=nn(0)
LET O=nn(1)
LET R=nn(2)
LET N=nn(3)
LET W=nn(4)
LET U=nn(5)
LET T=nn(6)
LET V=nn(7)
LET F=nn(8)
LET S=nn(9)
LET yy0= E+O+R
IF N= MOD( yy0,10) THEN
LET cy0= IP( yy0/10) !carry
!---
LET yy1= N+W+U +cy0
IF E=MOD( yy1,10) THEN
LET cy1= IP( yy1/10) !carry
!---
LET yy2= 2*O+T +cy1
IF V=MOD( yy2,10) THEN
LET cy2= IP( yy2/10) !carry
!---
LET yy3= F +cy2
IF E=MOD( yy3,10) AND S=IP( yy3/10) THEN
!---
PRINT " O N E"
PRINT " T W O"
PRINT " + F O U R"
PRINT "───────"
PRINT " S E V E N"
PRINT
PRINT " ";O ;N ;E
PRINT " ";T ;W ;O
PRINT " + ";F ;O ;U ;R
PRINT "───────"
PRINT S ;E ;V ;E ;N
PRINT
END IF
END IF
END IF
END IF
END SUB
!覆面算 ※10個の変数の場合
LET t0=TIME
PUBLIC NUMERIC ANSWER_COUNT !解答数
LET ANSWER_COUNT=0
DIM a(10) !異なる文字 ※ONETWFURSVの順
FOR i=1 TO 10 !0〜9
LET a(i)=i-1
NEXT i
CALL perm(a,1)
PRINT "計算時間=";TIME-t0
END
EXTERNAL SUB perm(a(), i) !n個の数字を使ってできる順列(辞書式でない)
LET N=UBOUND(a) !文字数
IF i<N THEN
FOR j=i TO N
LET t=a(i) !swap a(i),a(j)
LET a(i)=a(j)
LET a(j)=t
CALL perm(a,i+1)
LET t=a(i) !swap a(i),a(j)
LET a(i)=a(j)
LET a(j)=t
NEXT j
ELSE !すべてが確定したら、式を検証する
!!!MAT PRINT a; !debug
IF a(1)>0 AND a(4)>0 AND a(6)>0 AND a(9)>0 THEN !最上位桁は0でない
LET ONE = a(1)*100+a(2)*10+a(3)
LET TWO = a(4)*100+a(5)*10+a(1)
LET FOUR = a(6)*1000+ a(1)*100+a(7)*10+a(8)
LET SEVEN=a(9)*10000+a(3)*1000+a(10)*100+a(3)*10+a(2)
IF ONE+TWO+FOUR=SEVEN THEN !式が成立するなら
LET ANSWER_COUNT=ANSWER_COUNT+1 !解答数
PRINT ANSWER_COUNT
PRINT USING " ONE ####":ONE !結果の表示
PRINT USING " TWO ####":TWO
PRINT USING "+ FOUR ####":FOUR
PRINT "-------"
PRINT USING " SEVEN #####":SEVEN
PRINT
END IF
END IF
END IF
END SUB
実行結果
1
ONE 350
TWO 673
+ FOUR 9382
-------
SEVEN 10405
2
ONE 350
TWO 683
+ FOUR 9372
-------
SEVEN 10405
3
ONE 530
TWO 625
+ FOUR 9548
-------
SEVEN 10703
4
ONE 530
TWO 645
+ FOUR 9528
-------
SEVEN 10703
5
ONE 630
TWO 526
+ FOUR 9647
-------
SEVEN 10803
6
ONE 630
TWO 546
+ FOUR 9627
-------
SEVEN 10803
7
ONE 940
TWO 729
+ FOUR 8935
-------
SEVEN 10604
8
ONE 940
TWO 739
+ FOUR 8925
-------
SEVEN 10604
他の覆面算にも応用できるようにしました。
次の3箇所を変更するだけで実行できると思います。
1.変数 k の値(LET k=4 ! 単語の個数)
2.各単語のDATA(DATA "ONE","TWO","FOUR","SEVEN")
3.IF文で判定する計算式
(IF h0=0 AND change("ONE")+change("TWO")+change("FOUR")=change("SEVEN") THEN)
SEND+MORE=MONEY で試してみてください。
OPTION ARITHMETIC NATIVE
DECLARE EXTERNAL SUB perm,charac,headset
DECLARE EXTERNAL FUNCTION random
PUBLIC NUMERIC k,num(10),head(30),check(0 TO 9)
PUBLIC STRING word$(30),c$(10)
LET k=4 ! 単語の個数
!LET k=3
FOR i=1 TO k
READ word$(i)
NEXT i
DATA "ONE","TWO","FOUR","SEVEN"
!DATA "SEND","MORE","MONEY"
CALL charac(word$)
CALL headset
RANDOMIZE
MAT check=ZER
FOR i=1 TO 10
LET num(i)=random
NEXT i
!
CALL perm(num,1)
END
!
!
REM 1〜nの順列を辞書式順序で生成する。
!十進BASIC添付"\BASICw32\SAMPLE\PERMUTAT.BAS"参照
EXTERNAL SUB perm(a(),n)
OPTION ARITHMETIC NATIVE
DECLARE FUNCTION change
IF n=10 THEN
LET h0=0
FOR ii=1 TO k
IF num(head(ii))=0 THEN
LET h0=1 ! 先頭文字が 0
EXIT FOR
END IF
NEXT ii
IF h0=0 AND change("ONE")+change("TWO")+change("FOUR")=change("SEVEN") THEN
!IF h0=0 AND change("SEND")+change("MORE")=change("MONEY") THEN
FOR ii=1 TO k
PRINT word$(ii);" =";change(word$(ii))
NEXT ii
FOR ii=1 TO 10
PRINT c$(ii);"=";STR$(num(ii));" ";
NEXT ii
PRINT
STOP
END IF
ELSE
FOR i=n TO 10
LET t=a(i)
FOR j=i-1 TO n STEP -1
LET a(j+1)=a(j)
NEXT j
LET a(n)=t
CALL perm(a,n+1)
LET t=a(n)
FOR j=n TO i-1
LET a(j)=a(j+1)
NEXT j
LET a(i)=t
NEXT i
END IF
FUNCTION change(w$)
LET l=LEN(w$)
LET s=0
FOR i=1 TO l
FOR j=1 TO 10
IF c$(j)=w$(i:i) THEN
LET s=s+10^(l-i)*num(j)
EXIT FOR
END IF
NEXT j
NEXT i
LET change=s
END FUNCTION
END SUB
!
EXTERNAL SUB charac(a$())
OPTION ARITHMETIC NATIVE
LET s=SIZE(a$)
LET c=1
LET c$(1)=a$(1)(1:1)
FOR i=1 TO s
FOR j=1 TO LEN(a$(i))
LET cc=0
FOR kk=1 TO c
IF a$(i)(j:j)<>c$(kk) THEN LET cc=cc+1
NEXT kk
IF cc=c THEN
LET c=c+1
LET c$(c)=a$(i)(j:j)
IF c=10 THEN EXIT SUB
END IF
NEXT j
NEXT i
END SUB
!
EXTERNAL SUB headset
OPTION ARITHMETIC NATIVE
FOR i=1 TO k
FOR j=1 TO 10
IF word$(i)(1:1)=c$(j) THEN LET head(i)=j !先頭文字
NEXT j
NEXT i
END SUB
!
EXTERNAL FUNCTION random
OPTION ARITHMETIC NATIVE
LET r=INT(10*RND)
IF check(r)=0 THEN
LET random=r
LET check(r)=1
ELSE
LET random=random
END IF
END FUNCTION
!覆面算(nPr順列+枝狩り)
DECLARE EXTERNAL SUB F.perm !外部手続き、変数を宣言する
DECLARE EXTERNAL NUMERIC F.ANSWER_COUNT
LET t0=TIME
CALL perm(0, 1) !キャリーは0、一の位から
IF ANSWER_COUNT=0 THEN PRINT "解なし"
PRINT "計算時間=";TIME-t0
END
MODULE F
SHARE STRING c$
! ONE ↓※一の位からa()に順に割り付ける
! TWO ↓
!+ FOUR ↓
!------
! SEVEN ↓
LET c$="EORNWUTVFS" !異なる文字 ←←←←← ※差し替え
IF LEN(c$)>10 THEN
PRINT "指定できる文字は10文字以内です。"
STOP
END IF
SHARE NUMERIC a(10) !文字に設定した数値(0〜9)
MAT a=ZER(LEN(c$)) !文字数と同数に調整する
SHARE NUMERIC f(0 TO 9) !文字に割り当てる数(0〜9)フラグ用 ※
MAT f=ZER
PUBLIC NUMERIC ANSWER_COUNT !解答数
LET ANSWER_COUNT=0
EXTERNAL FUNCTION fnVAL(w$) !文字表現の数を数値に換える
LET v=0
FOR i=1 TO LEN(w$)
LET p=POS(c$,w$(i:i))
LET v=v*10+a(p)
NEXT i
LET fnVAL=v
END FUNCTION
PUBLIC SUB perm
EXTERNAL SUB perm(cy, L) !nPr順列での数の組を生成する
FOR nm=LBOUND(f) TO UBOUND(f) !重複を避けて、0〜9の数字を割り当てる
IF f(nm)=0 THEN
LET f(nm)=1 !使用中フラグをONにする
LET a(L)=nm !L番目を数nmとする
!----- ↓↓↓↓↓ ----- ※差し替え
SELECT CASE c$(L:L)
CASE "N" !一の位を確認する
LET k=fnVAL("E")+fnVAL("O")+fnVAL("R")
IF MOD(k,10)=fnVAL("N") THEN
CALL perm(INT(k/10), L+1)
END IF
CASE "U" !十の位を確認する
LET k=fnVAL("N")+fnVAL("W")+fnVAL("U") + cy
IF MOD(k,10)=fnVAL("E") THEN
CALL perm(INT(k/10), L+1)
END IF
CASE "V" !百の位を確認する
LET k=fnVAL("O")+fnVAL("T")+fnVAL("O") + cy
IF fnVAL("O")>0 AND fnVAL("T")>0 AND MOD(k,10)=fnVAL("V") THEN
CALL perm(INT(k/10), L+1)
END IF
CASE "S" !万と千の位を確認する
LET k=fnVAL("F") + cy
IF fnVAL("F")>0 AND fnVAL("S")>0 AND k=fnVAL("SE") THEN
LET ANSWER_COUNT=ANSWER_COUNT+1 !解答数
PRINT ANSWER_COUNT
PRINT USING " ONE ####":fnVAL("ONE") !結果の表示
PRINT USING " TWO ####":fnVAL("TWO")
PRINT USING "+ FOUR ####":fnVAL("FOUR")
PRINT "-------"
PRINT USING " SEVEN #####":fnVAL("SEVEN")
PRINT
!STOP !1つだけならコメントをはずす
END IF
CASE ELSE
IF L<LEN(c$) THEN CALL perm((cy), L+1) !次の文字へ ※cyは値渡し
END SELECT
!----- ↑↑↑↑↑ -----
LET f(nm)=0 !未使用
END IF
NEXT nm
END SUB
END MODULE
Rolling Cube1
さいころが9個(3×3)入る箱があり、中央にはさいころがなく、周りに8個のさいころが1の目を下にして配置されている。
さいころを空き地に転がすことで、全てのさいころの目が1が出現するようにせよ。
Rolling Cube2
8×8のオセロ板の左上に1の目を上にしたさいころがある。全てのマス目を1の目が出現しないよう(上の面に1の目が出ない。)に転がしていき、最後に右上のマス目で終了する時初めて1の目が現れること。
Rolling Cube2が
LET s$="RRRDLDLULDDDDDDRURDRUULLUURDRUURDDRURDDLLDDRURDRUUUUUULDLULURRR"
で無事到着しました。
長いもやもやがスッキリした気分です。
そういえば、以前こんな問題を山中さんから出題されていましたね。
すっかり忘れていました。こんなところで繋がるとは思ってもいませんでした。
強力なプログラム有り難うございました。
!問題
! さいころが1つ、8×8の盤の左上隅に1の面を上に乗っています。
! このさいころを全てのマスを1度だけ通って右上隅に転がして移動させます。
! このとき、途中で1の面が上に来てはいけません。
! 最後に右上隅に来たときは、1の面が上になるようにしてください。
DECLARE EXTERNAL NUMERIC RollCube.A() !外部手続き、変数
DECLARE EXTERNAL NUMERIC Map.ANSWER_COUNT
DECLARE EXTERNAL SUB Map.visit
LET t0=TIME
CALL visit(2,2,1,A) !左上の座標(Y,X)=(1,1) ※外壁を考慮する
IF ANSWER_COUNT=0 THEN PRINT "解なし"
PRINT "実行時間=";TIME-t0
END
MODULE Map !マップの構築とその経路探索
SHARE NUMERIC SX,SY !マップの大きさ ※
LET SY=8 !縦
LET SX=8 !横
SHARE NUMERIC M(20,20) !マップ
MAT M=ZER(SY+2,SX+2)
FOR i=1 TO SX+2 !外壁をつくる ※番兵
LET M(1,i)=-1
LET M(SY+2,i)=-1
NEXT i
FOR i=1 TO SY+2
LET M(i,1)=-1
LET M(i,SX+2)=-1
NEXT i
!内壁をつくる ※
!!!MAT PRINT M; !debug
SHARE NUMERIC EX,EY !終点の座標 ※
LET EX=SX+1 !右上隅 ※外壁を考慮する
LET EY=1+1
SHARE NUMERIC DIST !経路を1度だけ通る最大距離
FOR i=2 TO SY+1
FOR j=2 TO SX+1
IF M(i,j)=0 THEN LET DIST=DIST+1
NEXT j
NEXT i
!!!PRINT DIST !debug
PUBLIC NUMERIC ANSWER_COUNT !解答数
LET ANSWER_COUNT=0
SET WINDOW 0,1,1,0 !---------- trace
PUBLIC SUB vist
EXTERNAL SUB visit(yy,xx,Cnt,T()) !経路(1度だけ通る)を探索する
DECLARE EXTERNAL SUB RollCube.PermMultiply,RollCube.PermPrintOut !外部手続き、変数
DECLARE EXTERNAL NUMERIC RollCube.U(),RollCube.D(),RollCube.L(),RollCube.R()
DECLARE EXTERNAL NUMERIC RollCube.DX(),RollCube.DY()
DIM TT(UBOUND(T)) !作業用
LET M(yy,xx)=Cnt !足跡
SET DRAW mode hidden !---------- trace start
CLEAR
FOR i=1 TO SY+2
FOR j=1 TO SX+2
PLOT TEXT, AT 0.06*j,0.06*i: STR$(M(i,j))
NEXT j
NEXT i
SET DRAW mode explicit !---------- trace end
IF (xx=EX AND yy=EY) THEN !終点なら
IF Cnt=DIST AND T(3)=1 THEN !すべてのマスを経由して、1の目なら
LET ANSWER_COUNT=ANSWER_COUNT+1
PRINT "No.";ANSWER_COUNT
MAT PRINT USING(REPEAT$(" ##",UBOUND(M,2))): M
END IF
ELSE
FOR i=1 TO 4 !上下左右の4近傍
LET ty=yy+DY(i)
LET tx=xx+DX(i)
IF DIST=SY*SX AND Cnt<(SY-1)*(SX-1) AND (ty>SY OR tx>SX) THEN !マップを分割することを防ぐ
ELSE !!!!!※開始位置が最下行以外
IF M(ty,tx)=0 THEN !未踏なら
SELECT CASE i !さいころを転がしてみる
CASE 1
CALL PermMultiply(T,U,TT)
CASE 2
CALL PermMultiply(T,D,TT)
CASE 3
CALL PermMultiply(T,L,TT)
CASE 4
CALL PermMultiply(T,R,TT)
CASE ELSE
END SELECT
IF Cnt+1=DIST OR TT(3)<>1 THEN CALL visit(ty,tx,Cnt+1,TT) !1の目以外なら、次へ
END IF
END IF !!!!!
NEXT i
END IF
LET M(yy,xx)=0 !元に戻す
END SUB
END MODULE
MODULE RollCube !さいころを転がす
PUBLIC NUMERIC DX(4),DY(4) !上下左右の4近傍
DATA 0,0,-1,1
DATA -1,1, 0,0
MAT READ DX
MAT READ DY
!展開図の配置と面番号(配列の添え字)との関係
! □ 後 1
!□□□□ 左上右下 2345
! □ 正 6
PUBLIC NUMERIC A(6)
DATA 5,4,1,3,6,2 !目の配置 ※展開図参照
MAT READ A
PUBLIC NUMERIC U(6),D(6),L(6),R(6) !置換
! 1,2,3,4,5,6
DATA 3,2,6,4,1,5 !上 ※正面を上面にする(図での水平軸)回転
!!!DATA 5,2,1,4,6,3 !下
DATA 1,3,4,5,2,6 !左
!!!DATA 1,5,2,3,4,6 !右
MAT READ U
CALL PermInverse(U,D)
!!!MAT READ D
MAT READ L
CALL PermInverse(L,R)
!!!MAT READ R
!置換(Permutation)の計算
PUBLIC SUB PermPrintOut
EXTERNAL SUB PermPrintOut(A()) !表示する
MAT PRINT USING(REPEAT$(" ##",UBOUND(A))): A;
PRINT
END SUB
PUBLIC SUB PermIdentity
EXTERNAL SUB PermIdentity(A()) !恒等置換
FOR i=1 TO UBOUND(A)
LET A(i)=i
NEXT i
END SUB
PUBLIC SUB PermInverse
EXTERNAL SUB PermInverse(A(), iA()) !逆置換 ※iAはA以外の配列を指定すること
FOR i=1 TO UBOUND(A)
LET iA(A(i))=i
NEXT i
END SUB
PUBLIC SUB PermMultiply
EXTERNAL SUB PermMultiply(A(),B(), AB()) !積AB ※ABはA以外かつB以外の配列を指定すること
LET ua=UBOUND(A)
LET ub=UBOUND(B)
IF ua=ub THEN
FOR i=1 TO ua
LET AB(i)=A(B(i)) !※合成写像(AB)(i)=A(B(i))
NEXT i
ELSE
PRINT "次元が違います。A=";ua;" B=";ub
STOP
END IF
END SUB
END MODULE
!問題
! さいころが1つ、8×8の盤の左上隅に1の面を上に乗っています。
! このさいころを全てのマスを1度だけ通って右上隅に転がして移動させます。
! このとき、途中で1の面が上に来てはいけません。
! 最後に右上隅に来たときは、1の面が上になるようにしてください。
!その他では、1×1、1×5、2×2、4×2、4×6など
DECLARE EXTERNAL NUMERIC RollCube.A() !外部手続き、変数
DECLARE EXTERNAL NUMERIC Map.ANSWER_COUNT
DECLARE EXTERNAL SUB Map.visit
LET t0=TIME
CALL visit(2,2,1,A) !左上の座標(Y,X)=(1,1) ※外壁を考慮する
IF ANSWER_COUNT=0 THEN PRINT "解なし"
PRINT "実行時間=";TIME-t0;"秒"
END
MODULE Map !マップの構築とその経路探索
SHARE NUMERIC SX,SY !マップの大きさ ※
LET SY=8 !縦
LET SX=8 !横
SHARE NUMERIC M(20,20) !マップ
MAT M=ZER(SY+2,SX+2)
FOR i=1 TO SX+2 !外壁をつくる ※番兵
LET M(1,i)=-1
LET M(SY+2,i)=-1
NEXT i
FOR i=1 TO SY+2
LET M(i,1)=-1
LET M(i,SX+2)=-1
NEXT i
!内壁をつくる ※
!!!MAT PRINT M; !debug
SHARE NUMERIC EX,EY !終点の座標 ※
LET EX=SX+1 !右上隅 ※外壁を考慮する
LET EY=1+1
SHARE NUMERIC DIST !経路を1度だけ通る最大距離
FOR i=2 TO SY+1
FOR j=2 TO SX+1
IF M(i,j)=0 THEN LET DIST=DIST+1
NEXT j
NEXT i
!!!PRINT DIST !debug
PUBLIC NUMERIC ANSWER_COUNT !解答数
LET ANSWER_COUNT=0
SET WINDOW 0,1,1,0 !---------- trace
PUBLIC SUB vist
EXTERNAL SUB visit(yy,xx,Cnt,T()) !経路(1度だけ通る)を探索する
DECLARE EXTERNAL SUB RollCube.PermMultiply,RollCube.PermPrintOut !外部手続き、変数
DECLARE EXTERNAL NUMERIC RollCube.U(),RollCube.D(),RollCube.L(),RollCube.R()
DECLARE EXTERNAL NUMERIC RollCube.DX(),RollCube.DY()
DIM TT(UBOUND(T)) !作業用
LET M(yy,xx)=Cnt !足跡
SET DRAW mode hidden !---------- trace start
CLEAR
FOR i=1 TO SY+2 !マップを表示する
FOR j=1 TO SX+2
PLOT TEXT, AT 0.06*j,0.06*i: STR$(M(i,j))
NEXT j
NEXT i
SET DRAW mode explicit !---------- trace end
IF (xx=EX AND yy=EY) THEN !終点なら
IF Cnt=DIST AND T(3)=1 THEN !すべてのマスを経由して、1の目なら
LET ANSWER_COUNT=ANSWER_COUNT+1 !解を表示する
PRINT "No.";ANSWER_COUNT
MAT PRINT USING(REPEAT$(" ##",UBOUND(M,2))): M
END IF
ELSE
IF (Cnt>=DIST/5 AND Cnt<=DIST*4/5) AND MOD(Cnt,4)=0 THEN !孤立領域の有無 ※要調整
IF ChkDivdRegion(M)<>0 THEN !あれば、終了!
LET M(yy,xx)=0 !!!!!
EXIT SUB
END IF
END IF
FOR i=4 TO 1 STEP -1 !上下左右の4近傍 ※ケースバイケース
!!FOR i=1 TO 4 !上下左右の4近傍 ※ケースバイケース
LET ty=yy+DY(i)
LET tx=xx+DX(i)
IF M(ty,tx)=0 THEN !未踏なら
SELECT CASE i !さいころを転がしてみる
CASE 1
CALL PermMultiply(T,U,TT)
CASE 2
CALL PermMultiply(T,D,TT)
CASE 3
CALL PermMultiply(T,L,TT)
CASE 4
CALL PermMultiply(T,R,TT)
CASE ELSE
END SELECT
IF Cnt+1=DIST OR TT(3)<>1 THEN CALL visit(ty,tx,Cnt+1,TT) !1の目以外なら、次へ
END IF
NEXT i
END IF
LET M(yy,xx)=0 !元に戻す
END SUB
EXTERNAL FUNCTION ChkDivdRegion(M(,)) !マップが分割されたかどうか確認する
LET ChkDivdRegion=0 !「なし」
LET i=2 !first scan
DO WHILE i<=SY+1
FOR j=2 TO SX+1
IF M(i,j)=0 THEN EXIT DO !1個目が見つかったら
NEXT j
LET i=i+1
LOOP
IF i>SY+1 AND j>SX+1 THEN EXIT FUNCTION !すべて埋まっている
CALL PaintRegion(M,i,j) !その領域を埋める
!!!MAT PRINT M; !debug
LET ChkDivdRegion=1 !「あり」
FOR i=2 TO SY+1 !second scan
FOR j=2 TO SX+1
IF M(i,j)=0 THEN EXIT FUNCTION !他にもあるなら、そこが孤立領域になる
NEXT j
NEXT i
LET ChkDivdRegion=0 !すべて埋まっている
END FUNCTION
EXTERNAL SUB PaintRegion(M(,),i,j) !領域を塗りつぶす
LET M(i,j)=-2
IF M(i-1,j)=0 THEN CALL PaintRegion(M,i-1,j)
IF M(i,j-1)=0 THEN CALL PaintRegion(M,i,j-1)
IF M(i,j+1)=0 THEN CALL PaintRegion(M,i,j+1)
IF M(i+1,j)=0 THEN CALL PaintRegion(M,i+1,j)
END SUB
END MODULE
MODULE RollCube !さいころを転がす
PUBLIC NUMERIC DX(4),DY(4) !上下左右の4近傍
DATA 0,0,-1,1
DATA -1,1, 0,0
MAT READ DX
MAT READ DY
!展開図の配置と面番号(配列の添え字)との関係
! □ 後 1
!□□□□ 左上右下 2345
! □ 正 6
PUBLIC NUMERIC A(6)
DATA 5,4,1,3,6,2 !目の配置 ※展開図参照
MAT READ A
PUBLIC NUMERIC U(6),D(6),L(6),R(6) !置換
! 1,2,3,4,5,6
DATA 3,2,6,4,1,5 !上 ※正面を上面にする(図での水平軸)回転
!!!DATA 5,2,1,4,6,3 !下
DATA 1,3,4,5,2,6 !左
!!!DATA 1,5,2,3,4,6 !右
MAT READ U
CALL PermInverse(U,D)
!!!MAT READ D
MAT READ L
CALL PermInverse(L,R)
!!!MAT READ R
!置換(Permutation)の計算
PUBLIC SUB PermPrintOut
EXTERNAL SUB PermPrintOut(A()) !表示する
MAT PRINT USING(REPEAT$(" ##",UBOUND(A))): A;
PRINT
END SUB
PUBLIC SUB PermIdentity
EXTERNAL SUB PermIdentity(A()) !恒等置換
FOR i=1 TO UBOUND(A)
LET A(i)=i
NEXT i
END SUB
PUBLIC SUB PermInverse
EXTERNAL SUB PermInverse(A(), iA()) !逆置換 ※iAはA以外の配列を指定すること
FOR i=1 TO UBOUND(A)
LET iA(A(i))=i
NEXT i
END SUB
PUBLIC SUB PermMultiply
EXTERNAL SUB PermMultiply(A(),B(), AB()) !積AB ※ABはA以外かつB以外の配列を指定すること
LET ua=UBOUND(A)
LET ub=UBOUND(B)
IF ua=ub THEN
FOR i=1 TO ua
LET AB(i)=A(B(i)) !※合成写像(AB)(i)=A(B(i))
NEXT i
ELSE
PRINT "次元が違います。A=";ua;" B=";ub
STOP
END IF
END SUB
END MODULE
!パズル - 将棋駒の入れ替え
!3×3 1行目と3行目を入れ替える
! 銀金銀 歩歩歩
! 角 飛 → 角 飛
! 歩歩歩 銀金銀
!答え 30手
LET t0=TIME
PUBLIC NUMERIC xSIZE,ySIZE !盤の大きさ
LET xSIZE=3
LET ySIZE=3
PUBLIC NUMERIC cSPACE !空白の数
LET cSPACE=1
DECLARE STRING INIT$ !初期の状態
LET INIT$="銀金銀角 飛歩歩歩"
PUBLIC STRING GOAL$ !完成の状態
LET GOAL$="歩歩歩角 飛銀金銀" !完全一致
!!LET GOAL$="歩歩歩○○○○○○" !部分一致
PUBLIC STRING KO$(6) !駒の種類と移動可能範囲 ※8近傍 動きは将棋と同じ
DATA "×○××歩××××"
DATA "○○○×銀×○×○"
DATA "○○○○金○×○×"
DATA "○×○×角×○×○"
DATA "×○×○飛○×○×"
DATA "○○○○玉○○○○"
FOR i=1 TO 6
READ KO$(i)
NEXT i
PUBLIC NUMERIC LIM !手数の上限 →最少手数
LET LIM=200
PUBLIC STRING ANS$(0 TO 200) !上限までの手順
PUBLIC STRING STK$(0 TO 200) !局面の記録 ※スタック
FOR i=0 TO 200
LET ANS$(i)=""
LET STK$(i)=""
NEXT i
!PUBLIC NUMERIC LVL(0 TO 200) !----- trace -----
!MAT LVL=ZER
IF LEN(INIT$)<>ySIZE*xSIZE THEN
PRINT "盤の大きさ(xSIZE,ySIZE)と駒の数(INIT$)が合いません。"
STOP
END IF
IF LEN(GOAL$)<>ySIZE*xSIZE THEN
PRINT "盤の大きさ(xSIZE,ySIZE)と駒の数(GOAL$)が合いません。"
STOP
END IF
LET STK$(0)=INIT$
CALL backtrack(0) !0手目
IF ANS$(0)="" THEN
PRINT "解なし"
ELSE
PRINT
FOR i=1 TO LIM !解を表示する
PRINT ANS$(i)
NEXT i
END IF
PRINT "計算時間=";TIME-t0;"秒"
END
EXTERNAL SUB backtrack(L) !1手ずつ打っていき、行き詰まれば元に戻ってやり直す
LET bd$=stk$(L) !現在の局面
!---------- ↓↓↓↓↓ ---------- trace
!SET DRAW mode hidden !ちらつき防止の開始
!CLEAR
!FOR i=1 TO L
! PLOT TEXT ,AT 0.4+0.05*MOD(i-1,10),0.95-0.04*INT((i-1)/10): STR$(LVL(i))
!NEXT i
!FOR i=1 TO ySIZE
! LET t=(i-1)*xSIZE
! PLOT TEXT ,AT 0.1,0.50-i*0.05: bd$(t+1:t+xSIZE)
!NEXT i
!SET DRAW mode explicit !ちらつき防止の終了
!---------- ↑↑↑↑↑ ----------
LET C=0 !枝刈り ※「残りの手数」と「駒の位置が一致しない数」との関係より
FOR i=1 TO ySIZE*xSIZE
SELECT CASE GOAL$(i:i)
CASE "×"," ","○" !何でも良い
CASE ELSE !完全一致
IF GOAL$(i:i)<>bd$(i:i) THEN LET C=C+1 !C個の駒を一致させる必要があるが、
END SELECT
NEXT i
IF L+C>LIM THEN EXIT SUB !残りの手数が足りないので、不可能!!!
IF C=0 THEN !完成なら、手順を記録しておく
PRINT L;"手"
FOR i=0 TO L
LET ANS$(i)=STK$(i)
NEXT i
PRINT STK$(L) !debug
LET LIM=L !上限を狭める
END IF
IF L>=LIM THEN EXIT SUB !上限まで
LET CntOfSP=0
FOR p=1 TO ySIZE*xSIZE !盤を走査して空白に駒を移動させる
IF bd$(p:p)=" " THEN
LET px=MOD(p-1,xSIZE)+1 !水平・垂直の座標へ
LET py=INT((p-1)/xSIZE)+1
!!!FOR d=1 TO 9 !隣接する駒を探す ※ケースバイケース
FOR d=9 TO 1 STEP -1 !隣接する駒を探す ※ケースバイケース
IF d=5 THEN
ELSE
LET mx=px + MOD(d-1,3)-1 !移動元の座標 ※dを水平・垂直の差分dx,dyへ
LET my=py + INT((d-1)/3)-1
IF (mx>=1 AND mx<=xSIZE) AND (my>=1 AND my<=ySIZE) THEN !盤内か確認する
LET mp=(my-1)*xSIZE + mx !連番へ
LET t$=bd$(mp:mp)
IF t$="×" OR t$=" " THEN
ELSE
FOR a=1 TO UBOUND(KO$) !駒の属性を得る
IF t$=KO$(a)(5:5) THEN EXIT FOR
NEXT a
IF KO$(a)(10-d:10-d)="×" THEN !移動可能範囲なら
ELSE
LET w$=bd$
LET w$(p:p)=KO$(a)(5:5) !移動させる
LET w$(mp:mp)=" "
FOR t=L TO 0 STEP -1 !最近の局面から順に新しい手かどうか確認する
IF STK$(t)=w$ THEN EXIT FOR
NEXT t
IF t<0 THEN
!LET LVL(L+1)=CntOfSP*10+d !----- trace -----
LET STK$(L+1)=w$ !記録して、次の局面へ
CALL backtrack(L+1)
END IF
END IF
END IF
END IF
END IF
NEXT d
LET CntOfSP=CntOfSP+1
IF CntOfSP=cSPACE THEN EXIT FOR !空白の数だけ
END IF
NEXT p
END SUB
!●問題
!8個のさいころが、3×3の盤に1の目を上にして他の目も同じ向きで配置されています。
!空いているマスに転がして、すべての目が6になるようにしてください。
!置換(Permutation)の計算
SUB PermPrintOut(A()) !表示する
MAT PRINT USING(REPEAT$(" ##",UBOUND(A))): A;
PRINT
END SUB
SUB PermIdentity(A()) !恒等置換
FOR i=1 TO UBOUND(A)
LET A(i)=i
NEXT i
END SUB
SUB PermInverse(A(), iA()) !逆置換 ※iAはA以外の配列を指定すること
FOR i=1 TO UBOUND(A)
LET iA(A(i))=i
NEXT i
END SUB
SUB PermMultiply(A(),B(), AB()) !積AB ※ABはAかつB以外の配列を指定すること
FOR i=1 TO UBOUND(A)
LET AB(i)=A(B(i)) !※合成写像(AB)(i)=A(B(i))
NEXT i
END SUB
!-------------------- ここまでがサブルーチン
DIM U(6),D(6),L(6),R(6) !置換
! 1,2,3,4,5,6
DATA 3,2,6,4,1,5 !上 ※正面を上面にするの(図での水平軸)回転
!!!DATA 5,2,1,4,6,3 !下
DATA 1,3,4,5,2,6 !左
!!!DATA 1,5,2,3,4,6 !右
MAT READ U
CALL PermInverse(U,D)
!!!MAT READ D
MAT READ L
CALL PermInverse(L,R)
!!!MAT READ R
!---------- ↑↑↑↑↑ ----------
!展開図の配置と面番号(配列の添え字)との関係
! □ 後 1
!□□□□ 左上右下 2345
! □ 正 6
DIM T1(6),T2(6),T3(6),T4(6),T5(6),T6(6),T7(6),T8(6) !8個のさいころ
DATA 5,4,1,3,6,2 !目の配置 ※展開図参照
MAT READ T1
MAT T2=T1 !同じ向き
MAT T3=T1
MAT T4=T1
MAT T5=T1
MAT T6=T1
MAT T7=T1
MAT T8=T1
PICTURE dice(T()) !さいころを表示する ※原点基準
SET TEXT JUSTIFY "CENTER","HALF"
PLOT TEXT ,AT 0,-0.4: STR$(T(1)) !側面の目の数
PLOT TEXT ,AT -0.4,0: STR$(T(2))
PLOT TEXT ,AT 0.4,0: STR$(T(4))
PLOT TEXT ,AT 0,0.4: STR$(T(6))
LET nm=T(3) !上面の目の数
IF nm=1 THEN DRAW eye(4) !中央
IF nm=3 OR nm=5 THEN DRAW eye(1)
IF nm=2 OR nm=4 OR nm=5 OR nm=6 THEN !左斜め
DRAW eye(1) WITH SHIFT(0.25,0.25)
DRAW eye(1) WITH SHIFT(-0.25,-0.25)
END IF
IF nm=3 OR nm=4 OR nm=5 OR nm=6 THEN !右斜め
DRAW eye(1) WITH SHIFT(0.25,-0.25)
DRAW eye(1) WITH SHIFT(-0.25,0.25)
END IF
IF nm=6 THEN !中段
DRAW eye(1) WITH SHIFT(0.25,0)
DRAW eye(1) WITH SHIFT(-0.25,0)
END IF
END PICTURE
PICTURE eye(c) !1つの目を表示する
SET AREA COLOR c
DRAW disk WITH SCALE(0.1) !※要調整
END PICTURE
!---------- ↑↑↑↑↑ ----------
LET MY=3 !マップの大きさ
LET MX=3
DIM M(MY,MX) !さいころの配置 ※数字は番号、0は空き
DATA 1,2,3
DATA 4,0,5
DATA 6,7,8
MAT READ M
SUB dispMap !マップ上のさいころを表示する
FOR y=1 TO 3 !左上から順に
LET yy=y-0.5 !位置を算出する
FOR x=1 TO 3
LET xx=x-0.5
SELECT CASE M(y,x) !配置されたさいころに応じて
CASE 1
DRAW dice(T1) WITH SHIFT(xx,yy) !上面
CASE 2
DRAW dice(T2) WITH SHIFT(xx,yy)
CASE 3
DRAW dice(T3) WITH SHIFT(xx,yy)
CASE 4
DRAW dice(T4) WITH SHIFT(xx,yy)
CASE 5
DRAW dice(T5) WITH SHIFT(xx,yy)
CASE 6
DRAW dice(T6) WITH SHIFT(xx,yy)
CASE 7
DRAW dice(T7) WITH SHIFT(xx,yy)
CASE 8
DRAW dice(T8) WITH SHIFT(xx,yy)
CASE ELSE
END SELECT
NEXT x
NEXT y
END SUB
!---------- ↑↑↑↑↑ ----------
SUB move(T(),OP(),x,y,dx,dy) !さいころを回転移動させる
LET ANSWER_COUNT=ANSWER_COUNT+1
PRINT ANSWER_COUNT;"手"
DIM TT(6) !作業配列
CALL PermMultiply(T,OP,TT) !回転
MAT T=TT
LET w=M(y,x) !移動
LET M(y,x)=M(y+dy,x+dx)
LET M(y+dy,x+dx)=w
END SUB
SUB CalcDirection(x,y, T()) !移動可能な方向へ回転移動させる
IF y>=2 THEN !上に移動可能で
IF M(y-1,x)=0 THEN !空きマスなら
CALL move(T,U,x,y,0,-1) !回転移動させる
PRINT "UP";y;x
END IF
END IF
IF y<=2 THEN !下
IF M(y+1,x)=0 THEN
CALL move(T,D,x,y,0,1)
PRINT "DOWN";y;x
END IF
END IF
IF x>=2 THEN !左
IF M(y,x-1)=0 THEN
CALL move(T,L,x,y,-1,0)
PRINT "LEFT";y;x
END IF
END IF
IF x<=2 THEN !右
IF M(y,x+1)=0 THEN
CALL move(T,R,x,y,1,0)
PRINT "RIGHT";y;x
END IF
END IF
MAT PRINT M; !debug
END SUB
LET ANSWER_COUNT=0 !手数
SET WINDOW -1,MX+1,MY+1,-1 !表示領域
LET cx=1 !ポインタを左上に位置付ける
LET cy=1
DO
mouse poll x,y,left,right !マウスの情報を得る
LET xx=INT(x) !位置
LET yy=INT(y)
IF xx>=0 AND xx<MX AND yy>=0 AND yy<MY THEN !マップ内なら
LET cx=xx+1 ![1,MX]
LET cy=yy+1 ![1,MY]
END IF
IF left=1 THEN !左ボタンが押されたら
SELECT CASE M(cy,cx) !さいころの番号を得る
CASE 1
CALL CalcDirection(cx,cy, T1) !回転移動させる
CASE 2
CALL CalcDirection(cx,cy, T2)
CASE 3
CALL CalcDirection(cx,cy, T3)
CASE 4
CALL CalcDirection(cx,cy, T4)
CASE 5
CALL CalcDirection(cx,cy, T5)
CASE 6
CALL CalcDirection(cx,cy, T6)
CASE 7
CALL CalcDirection(cx,cy, T7)
CASE 8
CALL CalcDirection(cx,cy, T8)
CASE ELSE
END SELECT
WAIT DELAY 0.2 !※要調整
END IF
SET DRAW mode hidden !ちらつき防止開始
CLEAR
DRAW grid !目盛り
SET LINE width 2 !ポインタを表示する
PLOT LINES: cx-1,cy-1; cx,cy-1; cx,cy; cx-1,cy; cx-1,cy-1
SET LINE width 1
CALL dispMap !さいころを表示する
SET TEXT JUSTIFY "LEFT","BOTTOM" !文字位置の調整
PLOT TEXT ,AT -0.5,-0.5: "移動するさいころを左クリックしてください。"
SET DRAW mode explicit !ちらつき防止終了
LOOP
END
!答え 38手
! URDL,DRUL,LDRR,UULD,RUL;LDR,ULDD,RRUL,LDRU,LURD
PUBLIC NUMERIC FLG
LET X=8.99999999865/1.999999991572
PRINT "修正前";X;"修正後";NUM(X);"理想値";9/2
LET X=7.000000000357/3.000000001345*5.99999999993247
PRINT "修正前";X;"修正後";NUM(X);"理想値";14
LET X=-15/6.00000000352*10.000000034/2.999999999247
PRINT "修正前";X;"修正後";NUM(X);"理想値";-25/3
LET X=SQR(2.500000000354)*SQR(2.9999999999999871)
PRINT "修正前";X;"修正後";NUM(X);"理想値";SQR(7.5)
LET X=EXP(1.50000000321)*EXP(3.9999999999992417)
PRINT "修正前";X;"修正後";NUM(X);"理想値";EXP(5.5)
END
EXTERNAL FUNCTION INTNUM(X)
LET EPS=1E-5 !'(要)調整
FOR I=0 TO 4 !'(要)調整
FOR J=0 TO 1
LET Y=ABS(X)*10^I+J*EPS
IF ABS(Y)-INT(ABS(Y))<=EPS THEN
LET INTNUM=SGN(X)*INT(ABS(Y))/10^I
LET FLG=1
EXIT FUNCTION
END IF
NEXT J
NEXT I
LET INTNUM=X
LET FLG=0
END FUNCTION
EXTERNAL FUNCTION NUM(X)
LET Y=INT(ABS(X))
LET P=ABS(X)-Y
LET K=INTNUM(X)
IF FLG=1 THEN
LET NUM=K
EXIT FUNCTION
END IF
LET K=INTNUM(1/P)
IF FLG=1 THEN
LET NUM=(Y+1/K)*SGN(X)
EXIT FUNCTION
END IF
LET K=INTNUM(X*X)
IF FLG=1 THEN
LET NUM=SQR(K)*SGN(X)
EXIT FUNCTION
END IF
IF X>0 THEN
LET K=INTNUM(LOG(X))
IF FLG=1 THEN
LET NUM=EXP(K)
EXIT FUNCTION
END IF
END IF
IF ABS(X)<228 THEN
LET K=INTNUM(EXP(X))
IF FLG=1 THEN
LET NUM=LOG(K)*SGN(X)
EXIT FUNCTION
END IF
END IF
LET NUM=X
END FUNCTION
OPTION ARITHMETIC COMPLEX
LET X=COMPLEX(1,-2)
LET N=5
DIM A(N)
PRINT "X=";X;"(";REAL(X);IMAG(X);")"
PRINT "SIN=";CSIN(X);CSIN2(X)
PRINT "COS=";CCOS(X);CCOS2(X)
PRINT "TAN=";CTAN(X);CTAN2(X)
PRINT "COSEC=";CCOSEC(X);CCOSEC2(X)
PRINT "SEC=";CSEC(X);CSEC2(X)
PRINT "COTAN=";CCOTAN(X);CCOTAN2(X)
PRINT "SINH=";CSINH(X);CSINH2(X)
PRINT "COSH=";CCOSH(X);CCOSH2(X)
PRINT "TANH=";CTANH(X);CTANH2(X)
PRINT "COSECH=";CCOSECH(X);CCOSECH2(X)
PRINT "SECH=";CSECH(X);CSECH2(X)
PRINT "COTANH=";CCOTANH(X);CCOTANH2(X)
PRINT "平方根=";CSQR(X);CEXP(CLOG(X)/2)
CALL CNPOW(X,N,A)
PRINT N;"乗根"
FOR I=1 TO N
PRINT I;":";A(I);A(I)^N
NEXT I
LET Y=COMPLEX(1,2)
PRINT "X^Y=";CPOW(X,Y);CEXP(Y*CLOG(X))
END
! 三角関数
EXTERNAL FUNCTION CSIN(Z) !'sine
OPTION ARITHMETIC COMPLEX
LET X=RE(Z)
LET Y=IM(Z)
LET XR = SIN(X) * COSH(Y)
LET XI = COS(X) * SINH(Y)
LET CSIN=COMPLEX(XR,XI)
END FUNCTION
EXTERNAL FUNCTION CSIN2(Z)
OPTION ARITHMETIC COMPLEX
LET I=SQR(-1)
LET CSIN2=(CEXP(I*Z)-CEXP(-I*Z))/(2*I)
END FUNCTION
EXTERNAL FUNCTION CCOS(Z) !'cosine
OPTION ARITHMETIC COMPLEX
LET X=RE(Z)
LET Y=IM(Z)
LET XR = COS(X) * COSH(Y)
LET XI = -SIN(X) * SINH(Y)
LET CCOS=COMPLEX(XR,XI)
END FUNCTION
EXTERNAL FUNCTION CCOS2(Z)
OPTION ARITHMETIC COMPLEX
LET I=SQR(-1)
LET CCOS2=(CEXP(I*Z)+CEXP(-I*Z))/2
END FUNCTION
EXTERNAL FUNCTION CTAN(Z) !'tangent
OPTION ARITHMETIC COMPLEX
LET X=RE(Z)
LET Y=IM(Z)
LET D = COS(2 * X) + COSH(2 * Y)
LET XR = SIN(2 * X) / D
LET XI = SINH(2 * Y) / D
LET CTAN=COMPLEX(XR,XI)
END FUNCTION
EXTERNAL FUNCTION CTAN2(Z)
OPTION ARITHMETIC COMPLEX
LET CTAN2=CSIN(Z)/CCOS(Z)
END FUNCTION
EXTERNAL FUNCTION CCOSEC(Z) !'cosecant
OPTION ARITHMETIC COMPLEX
LET X=RE(Z)
LET Y=IM(Z)
LET D=COS(X)^2*SINH(Y)^2+SIN(X)^2*COSH(Y)^2
LET XR=SIN(X)*COSH(Y)/D
LET XI=-COS(X)*SINH(Y)/D
LET CCOSEC=COMPLEX(XR,XI)
END FUNCTION
EXTERNAL FUNCTION CCOSEC2(Z)
OPTION ARITHMETIC COMPLEX
LET CCOSEC2=1/CSIN(Z)
END FUNCTION
EXTERNAL FUNCTION CSEC(Z) !'secant
OPTION ARITHMETIC COMPLEX
LET X=RE(Z)
LET Y=IM(Z)
LET D=SIN(X)^2*SINH(Y)^2+COS(X)^2*COSH(Y)^2
LET XR=COS(X)*COSH(Y)/D
LET XI=SIN(X)*SINH(Y)/D
LET CSEC=COMPLEX(XR,XI)
END FUNCTION
EXTERNAL FUNCTION CSEC2(Z)
OPTION ARITHMETIC COMPLEX
LET CSEC2=1/CCOS(Z)
END FUNCTION
EXTERNAL FUNCTION CCOTAN(Z) !'cotangent
OPTION ARITHMETIC COMPLEX
LET X=RE(Z)
LET Y=IM(Z)
LET D=COSH(2*Y)+COS(2*X)
LET DD=SINH(2*Y)^2+SIN(2*X)^2
LET XR=SIN(2*X)*D/DD
LET XI=-SINH(2*Y)*D/DD
LET CCOTAN=COMPLEX(XR,XI)
END FUNCTION
EXTERNAL FUNCTION CCOTAN2(Z)
OPTION ARITHMETIC COMPLEX
LET CCOTAN2=1/CTAN(Z)
END FUNCTION
! 逆三角関数
EXTERNAL FUNCTION CASIN(Z) !'arcsine
OPTION ARITHMETIC COMPLEX
LET X=RE(Z)
LET Y=IM(Z)
LET D=SQR((Y^2-X^2+1)^2+4*X^2*Y^2)
LET S=SQR(D-Y^2+X^2-1)/SQR(2)
LET SS=SQR(D+Y^2-X^2+1)/SQR(2)
IF X*Y>0 THEN
LET XR=-ATAN2(S-X,SS-Y)
LET XI=-LOG((SS-Y)^2+(X-S)^2)/2
ELSE
LET XR=ATAN2(S+X,SS-Y)
LET XI=-LOG((SS-Y)^2+(X+S)^2)/2
END IF
LET CASIN=COMPLEX(XR,XI)
END FUNCTION
EXTERNAL FUNCTION CASIN2(Z)
OPTION ARITHMETIC COMPLEX
LET CASIN2=CATAN(Z/CSQR(1-Z*Z))
END FUNCTION
EXTERNAL FUNCTION CASIN3(Z)
OPTION ARITHMETIC COMPLEX
LET I=SQR(-1)
LET CASIN3=-I*CLOG(CSQR(1-Z*Z)+Z*I)
END FUNCTION
EXTERNAL FUNCTION CACOS(Z) !'arccosine
OPTION ARITHMETIC COMPLEX
LET X=RE(Z)
LET Y=IM(Z)
LET D=SQR((Y^2-X^2+1)^2+4*X^2*Y^2)
LET S=SQR(D+Y^2-X^2+1)/SQR(2)
LET SS=SQR(D-Y^2+X^2-1)/SQR(2)
IF X*Y>0 THEN
LET XR=ATAN2(S+Y,X+SS)
LET XI=-LOG((S+Y)^2+(SS+X)^2)/2
ELSE
LET XR=ATAN2(S+Y,X-SS)
LET XI=-LOG((S+Y)^2+(X-SS)^2)/2
END IF
LET CACOS=COMPLEX(XR,XI)
END FUNCTION
EXTERNAL FUNCTION CACOS2(Z)
OPTION ARITHMETIC COMPLEX
LET I=SQR(-1)
LET CACOS2=-I*CLOG(Z+I*CSQR(1-Z*Z))
END FUNCTION
EXTERNAL FUNCTION CATAN(Z) !'arctangent
OPTION ARITHMETIC COMPLEX
LET X=RE(Z)
LET Y=IM(Z)
LET XR=(ATAN2(X,Y+1)+ATAN2(X,1-Y))/2
LET XI=-LOG((1-Y)^2+X^2)/4+LOG((Y+1)^2+X^2)/4
LET CATAN=COMPLEX(XR,XI)
END FUNCTION
EXTERNAL FUNCTION CATAN2(Z)
OPTION ARITHMETIC COMPLEX
LET I=SQR(-1)
LET CATAN2=I/2*CLOG((I+Z)/(I-Z))
END FUNCTION
EXTERNAL FUNCTION CACOSEC(Z) !'arccosecant
OPTION ARITHMETIC COMPLEX
LET X=RE(Z)
LET Y=IM(Z)
LET S=X^2-Y^2
LET SS=4*X^2*Y^2
LET D=S^2+SS
LET E=S/D
LET DD=SS/D^2
LET EE=Y^2/D-X^2/D+1
IF X*Y>=0 THEN
LET XR= ATAN2(SQR(SQR((1-E)^2+DD)+E-1)/SQR(2)+X/(X^2+Y^2),SQR(SQR((1-E)^2+DD)-E+1)/SQR(2)+Y/(X^2+Y^2))
LET XI=-LOG((SQR(SQR(EE^2+DD)+EE)/SQR(2)+Y/(Y^2+X^2))^2+(X/(X^2+Y^2)+SQR(SQR(EE^2+DD)-EE)/SQR(2))^2)/2
ELSE
LET XR=-ATAN2(SQR(SQR((1-E)^2+DD)+E-1)/SQR(2)-X/(X^2+Y^2),SQR(SQR((1-E)^2+DD)-E+1)/SQR(2)+Y/(X^2+Y^2))
LET XI=-LOG((SQR(SQR(EE^2+DD)+EE)/SQR(2)+Y/(Y^2+X^2))^2+(X/(X^2+Y^2)-SQR(SQR(EE^2+DD)-EE)/SQR(2))^2)/2
END IF
LET CACOSEC=COMPLEX(XR,XI)
END FUNCTION
EXTERNAL FUNCTION CACOSEC2(Z)
OPTION ARITHMETIC COMPLEX
LET CACOSEC2=CASIN(1/Z)
END FUNCTION
EXTERNAL FUNCTION CACOSEC3(Z)
OPTION ARITHMETIC COMPLEX
LET CACOSEC3=CATAN(1/CSQR(Z*Z-1))
END FUNCTION
EXTERNAL FUNCTION CASEC(Z) !'arcsecant
OPTION ARITHMETIC COMPLEX
LET X=RE(Z)
LET Y=IM(Z)
LET S=X^2-Y^2
LET SS=4*X^2*Y^2
LET D=S^2+SS
LET E=S/D
LET DD=SS/D^2
LET EE=Y^2/D-X^2/D+1
IF X*Y>=0 THEN
LET XR=ATAN2(SQR(SQR((1-E)^2+DD)-E+1)/SQR(2)-Y/(X^2+Y^2),X/(X^2+Y^2)-SQR(SQR((1-E)^2+DD)+E-1)/SQR(2))
LET XI=-LOG((SQR(SQR(EE^2+DD)+EE)/SQR(2)-Y/(Y^2+X^2))^2+(X/(X^2+Y^2)-SQR(SQR(EE^2+DD)-EE)/SQR(2))^2)/2
ELSE
LET XR=ATAN2(SQR(SQR((1-E)^2+DD)-E+1)/SQR(2)-Y/(X^2+Y^2),X/(X^2+Y^2)+SQR(SQR((1-E)^2+DD)+E-1)/SQR(2))
LET XI=-LOG((SQR(SQR(EE^2+DD)+EE)/SQR(2)-Y/(Y^2+X^2))^2+(X/(X^2+Y^2)+SQR(SQR(EE^2+DD)-EE)/SQR(2))^2)/2
END IF
LET CASEC=COMPLEX(XR,XI)
END FUNCTION
EXTERNAL FUNCTION CASEC2(Z)
OPTION ARITHMETIC COMPLEX
LET CASEC2=CATAN(CSQR(Z*Z-1))
END FUNCTION
EXTERNAL FUNCTION CASEC3(Z)
OPTION ARITHMETIC COMPLEX
LET CASEC3=CACOS(1/Z)
END FUNCTION
EXTERNAL FUNCTION CACOTAN(Z) !'arccotangent
OPTION ARITHMETIC COMPLEX
LET X=RE(Z)
LET Y=IM(Z)
LET D=X^2+Y^2
LET XR=(ATAN2(X/D,Y/D+1)+ATAN2(X/D,1-Y/D))/2
LET XI=-LOG((Y/D+1)^2+X^2/D^2)/4+LOG((1-Y/D)^2+X^2/D^2)/4
LET CACOTAN=COMPLEX(XR,XI)
END FUNCTION
EXTERNAL FUNCTION CACOTAN2(Z)
OPTION ARITHMETIC COMPLEX
LET CACOTAN2=CATAN(1/Z)
END FUNCTION
! 双曲線関数
EXTERNAL FUNCTION CSINH(Z) !'hyperbolic sine
OPTION ARITHMETIC COMPLEX
LET X=RE(Z)
LET Y=IM(Z)
LET XR = SINH(X) * COS(Y)
LET XI = COSH(X) * SIN(Y)
LET CSINH=COMPLEX(XR,XI)
END FUNCTION
EXTERNAL FUNCTION CSINH2(Z)
OPTION ARITHMETIC COMPLEX
LET CSINH2=(CEXP(Z)-CEXP(-Z))/2
END FUNCTION
EXTERNAL FUNCTION CCOSH(Z) !'hyperbolic cosine
OPTION ARITHMETIC COMPLEX
LET X=RE(Z)
LET Y=IM(Z)
LET XR = COSH(X) * COS(Y)
LET XI = SINH(X) * SIN(Y)
LET CCOSH=COMPLEX(XR,XI)
END FUNCTION
EXTERNAL FUNCTION CCOSH2(Z)
OPTION ARITHMETIC COMPLEX
LET CCOSH2=(CEXP(Z)+CEXP(-Z))/2
END FUNCTION
EXTERNAL FUNCTION CTANH(Z) !'hyperbolic tangent
OPTION ARITHMETIC COMPLEX
LET X=RE(Z)
LET Y=IM(Z)
LET D = COS(2 * Y) + COSH(2 * X)
LET XR = SINH(2 * X) / D
LET XI = SIN(2 * Y) / D
LET CTANH=COMPLEX(XR,XI)
END FUNCTION
EXTERNAL FUNCTION CTANH2(Z)
OPTION ARITHMETIC COMPLEX
LET CTANH2=CSINH(Z)/CCOSH(Z)
END FUNCTION
EXTERNAL FUNCTION CTANH3(Z)
OPTION ARITHMETIC COMPLEX
LET CTANH3=-CEXP(-Z)/(CEXP(Z)+CEXP(-Z))*2+1
END FUNCTION
EXTERNAL FUNCTION CCOSECH(Z) !'hyperbolic cosecant
OPTION ARITHMETIC COMPLEX
LET X=RE(Z)
LET Y=IM(Z)
LET D=COSH(X)^2*SIN(Y)^2+SINH(X)^2*COS(Y)^2
LET XR=SINH(X)*COS(Y)/D
LET XI=-COSH(X)*SIN(Y)/D
LET CCOSECH=COMPLEX(XR,XI)
END FUNCTION
EXTERNAL FUNCTION CCOSECH2(Z)
OPTION ARITHMETIC COMPLEX
LET CCOSECH2=1/CSINH(Z)
END FUNCTION
EXTERNAL FUNCTION CSECH(Z) !'hyperbolic secant
OPTION ARITHMETIC COMPLEX
LET X=RE(Z)
LET Y=IM(Z)
LET D=SINH(X)^2*SIN(Y)^2+COSH(X)^2*COS(Y)^2
LET XR=COSH(X)*COS(Y)/D
LET XI=-SINH(X)*SIN(Y)/D
LET CSECH=COMPLEX(XR,XI)
END FUNCTION
EXTERNAL FUNCTION CSECH2(Z)
OPTION ARITHMETIC COMPLEX
LET CSECH2=1/CCOSH(Z)
END FUNCTION
EXTERNAL FUNCTION CCOTANH(Z) !'hyperbolic cotangent
OPTION ARITHMETIC COMPLEX
LET X=RE(Z)
LET Y=IM(Z)
LET D=COS(2*Y)+COSH(2*X)
LET DD=SIN(2*Y)^2+SINH(2*X)^2
LET XR=SINH(2*X)*D/DD
LET XI=-SIN(2*Y)*D/DD
LET CCOTANH=COMPLEX(XR,XI)
END FUNCTION
EXTERNAL FUNCTION CCOTANH2(Z)
OPTION ARITHMETIC COMPLEX
LET CCOTANH2=1/CTANH(Z)
END FUNCTION
EXTERNAL FUNCTION CCOTANH3(Z)
OPTION ARITHMETIC COMPLEX
LET CCOTANH3=CEXP(-Z)/(CEXP(Z)-CEXP(-Z))*2+1
END FUNCTION
! 逆双曲線関数
EXTERNAL FUNCTION CASINH(Z) !'arc-hyperbolic sine
OPTION ARITHMETIC COMPLEX
LET X=RE(Z)
LET Y=IM(Z)
LET D=SQR((-Y^2+X^2+1)^2+4*X^2*Y^2)
IF X*Y>=0 THEN
LET XR=LOG((SQR(D+Y^2-X^2-1)/SQR(2)+Y)^2+(SQR(D-Y^2+X^2+1)/SQR(2)+X)^2)/2
LET XI=ATAN2(SQR(D+Y^2-X^2-1)/SQR(2)+Y,SQR(D-Y^2+X^2+1)/SQR(2)+X)
ELSE
LET XR=LOG((Y-SQR(D+Y^2-X^2-1)/SQR(2))^2+(SQR(D-Y^2+X^2+1)/SQR(2)+X)^2)/2
LET XI=-ATAN2(SQR(D+Y^2-X^2-1)/SQR(2)-Y,SQR(D-Y^2+X^2+1)/SQR(2)+X)
END IF
LET CASINH=COMPLEX(XR,XI)
END FUNCTION
EXTERNAL FUNCTION CASINH2(Z)
OPTION ARITHMETIC COMPLEX
LET CASINH2=CLOG(Z+CSQR(Z*Z+1))
END FUNCTION
EXTERNAL FUNCTION CACOSH(Z) !'arc-hyperbolic cosine
OPTION ARITHMETIC COMPLEX
LET X=RE(Z)
LET Y=IM(Z)
LET D=SQR(Y^2+(X+1)^2)
LET DD=SQR(Y^2+(X-1)^2)
IF Y>=0 THEN
LET XR=LOG((SQR(D+X+1)/2+SQR(DD+X-1)/2)^2+(SQR(D-X-1)/2+SQR(DD-X+1)/2)^2)
LET XI=2*ATAN2(SQR(D-X-1)/2+SQR(DD-X+1)/2,SQR(D+X+1)/2+SQR(DD+X-1)/2)
ELSE
LET XR=LOG((SQR(D+X+1)/2+SQR(DD+X-1)/2)^2+(-SQR(D-X-1)/2-SQR(DD-X+1)/2)^2)
LET XI=-2*ATAN2(SQR(D-X-1)/2+SQR(DD-X+1)/2,SQR(D+X+1)/2+SQR(DD+X-1)/2)
END IF
LET CACOSH=COMPLEX(XR,XI)
END FUNCTION
EXTERNAL FUNCTION CACOSH2(Z)
OPTION ARITHMETIC COMPLEX
LET CACOSH2=CLOG(Z+CSQR(Z*Z-1))
END FUNCTION
EXTERNAL FUNCTION CATANH(Z) !'arc-hyperbolic tangent
OPTION ARITHMETIC COMPLEX
LET X=RE(Z)
LET Y=IM(Z)
LET XR=LOG(Y^2+(X+1)^2)/4-LOG(Y^2+(1-X)^2)/4
LET XI=(ATAN2(Y,X+1)+ATAN2(Y,1-X))/2
LET CATANH=COMPLEX(XR,XI)
END FUNCTION
EXTERNAL FUNCTION CATANH2(Z)
OPTION ARITHMETIC COMPLEX
LET CATANH2=CLOG((1+Z)/(1-Z))/2
END FUNCTION
EXTERNAL FUNCTION CACOSECH(Z) !'arc-hyperbolic cosecant
OPTION ARITHMETIC COMPLEX
LET X=RE(Z)
LET Y=IM(Z)
LET S=(X^2-Y^2)^2+4*X^2*Y^2
LET D=Y^2/S
LET DD=X^2/S
LET SS=4*X^2*Y^2/S^2
LET E=(X^2-Y^2)/S
IF X*Y>0 THEN
LET
XR=LOG((-SQR(SQR((-D+DD+1)^2+SS)+D-DD-1)/SQR(2)-Y/(X^2+Y^2))^2+(SQR(SQR((-D+DD+1)^2+SS)-D+DD+1)/SQR(2)+X/(X^2+Y^2))^2)/2
LET XI=-ATAN2(SQR(SQR((E+1)^2+SS)-E-1)/SQR(2)+Y/(X^2+Y^2),SQR(SQR((E+1)^2+SS)+E+1)/SQR(2)+X/(X^2+Y^2))
ELSE
LET
XR=LOG((SQR(SQR((-D+DD+1)^2+SS)+D-DD-1)/SQR(2)-Y/(X^2+Y^2))^2+(SQR(SQR((-D+DD+1)^2+SS)-D+DD+1)/SQR(2)+X/(X^2+Y^2))^2)/2
LET XI=ATAN2(SQR(SQR((E+1)^2+SS)-E-1)/SQR(2)-Y/(X^2+Y^2),SQR(SQR((E+1)^2+SS)+E+1)/SQR(2)+X/(X^2+Y^2))
END IF
LET CACOSECH=COMPLEX(XR,XI)
END FUNCTION
EXTERNAL FUNCTION CACOSECH2(Z)
OPTION ARITHMETIC COMPLEX
LET CACOSECH2=CASINH(1/Z)
END FUNCTION
EXTERNAL FUNCTION CACOSECH3(Z)
OPTION ARITHMETIC COMPLEX
LET CACOSECH3=CLOG((CSQR(Z*Z+1)+1)/Z)
END FUNCTION
EXTERNAL FUNCTION CASECH(Z) !'arc-hyperbolic secant
OPTION ARITHMETIC COMPLEX
LET X=RE(Z)
LET Y=IM(Z)
LET D=X/(X^2+Y^2)
LET DD=Y^2/(X^2+Y^2)^2
IF Y>0 THEN
LET
XR=LOG((SQR(SQR((D+1)^2+DD)+D+1)/2+SQR(SQR((D-1)^2+DD)+D-1)/2)^2+(-SQR(SQR((D+1)^2+DD)-D-1)/2-SQR(SQR((D-1)^2+DD)-D+1)/2)^2)
LET
XI=-2*ATAN2(SQR(SQR((D+1)^2+DD)-D-1)/2+SQR(SQR((D-1)^2+DD)-D+1)/2,SQR(SQR((D+1)^2+DD)+D+1)/2+SQR(SQR((D-1)^2+DD)+D-1)/2)
ELSE
LET
XR=LOG((SQR(SQR((D+1)^2+DD)+D+1)/2+SQR(SQR((D-1)^2+DD)+D-1)/2)^2+(SQR(SQR((D+1)^2+DD)-D-1)/2+SQR(SQR((D-1)^2+DD)-D+1)/2)^2)
LET
XI=2*ATAN2(SQR(SQR((D+1)^2+DD)-D-1)/2+SQR(SQR((D-1)^2+DD)-D+1)/2,SQR(SQR((D+1)^2+DD)+D+1)/2+SQR(SQR((D-1)^2+DD)+D-1)/2)
END IF
LET CASECH=COMPLEX(XR,XI)
END FUNCTION
EXTERNAL FUNCTION CASECH2(Z)
OPTION ARITHMETIC COMPLEX
LET CASECH2=CACOSH(1/Z)
END FUNCTION
EXTERNAL FUNCTION CASECH3(Z)
OPTION ARITHMETIC COMPLEX
LET CASECH3=CLOG((CSQR(1-Z*Z)+1)/Z)
END FUNCTION
EXTERNAL FUNCTION CACOTANH(Z) !'arc-hyperbolic cotangent
OPTION ARITHMETIC COMPLEX
LET X=RE(Z)
LET Y=IM(Z)
LET D=X/(X^2+Y^2)
LET S=Y/(X^2+Y^2)
LET DD=S^2
LET XR=LOG((D+1)^2+DD)/4-LOG((1-D)^2+DD)/4
LET XI=(-ATAN2(S,D+1)-ATAN2(S,1-D))/2
LET CACOTANH=COMPLEX(XR,XI)
END FUNCTION
EXTERNAL FUNCTION CACOTANH2(Z)
OPTION ARITHMETIC COMPLEX
LET CACOTANH2=CATANH(1/Z)
END FUNCTION
EXTERNAL FUNCTION CACOTANH3(Z)
OPTION ARITHMETIC COMPLEX
LET CACOTANH3=CLOG((Z+1)/(Z-1))/2
END FUNCTION
! その他
EXTERNAL FUNCTION CABS(Z) !'絶対値
OPTION ARITHMETIC COMPLEX
LET CABS=SQR(RE(Z)^2+IM(Z)^2)
END FUNCTION
EXTERNAL FUNCTION CSQR(Z) !'平方根
OPTION ARITHMETIC COMPLEX
LET X=RE(Z)
LET Y=IM(Z)
LET R=SQR(X*X+Y*Y)
LET XR=SQR(R+X)/SQR(2)
IF Y>=0 THEN
LET XI=SQR(R-X)/SQR(2)
ELSE
LET XI=-SQR(R-X)/SQR(2)
END IF
LET CSQR=COMPLEX(XR,XI)
END FUNCTION
EXTERNAL FUNCTION CLOG(Z) !'対数
OPTION ARITHMETIC COMPLEX
LET X=RE(Z)
LET Y=IM(Z)
LET XR = LOG(X * X + Y * Y) / 2
LET XI = ATAN2(Y, X)
LET CLOG=COMPLEX(XR,XI)
END FUNCTION
EXTERNAL FUNCTION CEXP(Z) !'指数
OPTION ARITHMETIC COMPLEX
LET X=RE(Z)
LET Y=IM(Z)
LET XR = EXP(X) * COS(Y)
LET XI = EXP(X) * SIN(Y)
LET CEXP=COMPLEX(XR,XI)
END FUNCTION
EXTERNAL FUNCTION CARG(Z) !'偏角
OPTION ARITHMETIC COMPLEX
LET CARG = ATAN2(IM(Z), RE(Z))
END FUNCTION
EXTERNAL FUNCTION CPOW(X,Y) !'(A+Bi)^(C+Di)
OPTION ARITHMETIC COMPLEX
LET A=RE(X)
LET B=IM(X)
LET C=RE(Y)
LET D=IM(Y)
LET XR=(B^2+A^2)^(C/2)*EXP(-ATAN2(B,A)*D)*COS(LOG(B^2+A^2)*D/2+ATAN2(B,A)*C)
LET XI=(B^2+A^2)^(C/2)*EXP(-ATAN2(B,A)*D)*SIN(LOG(B^2+A^2)*D/2+ATAN2(B,A)*C)
LET CPOW=COMPLEX(XR,XI)
END FUNCTION
EXTERNAL SUB CNPOW(Z, N, V()) !'(A+Bi)^(1/N)
OPTION ARITHMETIC COMPLEX
LET X=RE(Z)
LET Y=IM(Z)
LET R = (X * X + Y * Y)^(1 / (2 * N))
LET TH = ATAN2(Y,X)
LET A = R * COS(TH / N)
LET B = R * SIN(TH / N)
FOR I = 1 TO N
LET C = COS(2 * PI / N * I)
LET S = SIN(2 * PI / N * I)
LET AA = A * C - B * S
LET BB = B * C + A * S
LET V(I) = COMPLEX(AA,BB)
NEXT I
END SUB
EXTERNAL FUNCTION CRUIJYO(Z, N) !'(A+Bi)^N
OPTION ARITHMETIC COMPLEX
LET X=RE(Z)
LET Y=IM(Z)
LET N = INT(N)
LET R = (X * X + Y * Y)^(N / 2)
LET TH=ATAN2(Y,X)
LET XR = R * COS(TH * N)
LET XI = R * SIN(TH * N)
LET CRUIJYO=COMPLEX(XR,XI)
END FUNCTION
EXTERNAL FUNCTION CCONJ(Z) !'共役数
OPTION ARITHMETIC COMPLEX
LET CCONJ=COMPLEX(RE(Z),-IM(Z))
END FUNCTION
EXTERNAL FUNCTION REAL(Z) !'実部
OPTION ARITHMETIC COMPLEX
LET REAL=CABS(Z)*COS(CARG(Z))
END FUNCTION
EXTERNAL FUNCTION IMAG(Z) !'虚部
OPTION ARITHMETIC COMPLEX
LET IMAG=CABS(Z)*SIN(CARG(Z))
END FUNCTION
EXTERNAL SUB CPRINT(Z)
OPTION ARITHMETIC COMPLEX
LET X=RE(Z)
LET Y=IM(Z)
IF X=0 AND Y=0 THEN
PRINT "0"
EXIT SUB
END IF
IF Y=0 THEN
IF X < 0 THEN PRINT "- ";
PRINT STR$(ABS(X))
EXIT SUB
END IF
IF X=0 THEN
IF Y < 0 THEN PRINT "- ";
IF ABS(Y)= 1 THEN
PRINT "i"
EXIT SUB
END IF
PRINT STR$(ABS(Y)); " i"
EXIT SUB
END IF
IF X < 0 THEN PRINT "- ";
PRINT STR$(ABS(X)); " ";
IF Y < 0 THEN PRINT "- "; ELSE PRINT "+ ";
IF ABS(Y)= 1 THEN
PRINT "i"
EXIT SUB
END IF
PRINT STR$(ABS(Y)); " i"
END SUB
EXTERNAL FUNCTION ATAN2(Y,X) !'-π〜π
OPTION ARITHMETIC COMPLEX
IF ABS(IM(X))<1E-4 AND ABS(IM(Y))<1E-4 THEN
LET X=RE(X)
LET Y=RE(Y)
ELSE
PRINT "ERROR!!"
STOP
END IF
LET ATAN2=ANGLE(X,Y)
!' LET L=ACOS(X/SQR(X*X+Y*Y))
!' IF Y<0 THEN LET ATAN2=-L ELSE LET ATAN2=L
END FUNCTION
!EXTERNAL FUNCTION ATAN2(Y,X) '0〜2π
!OPTION ARITHMETIC COMPLEX
!IF ABS(IM(X))<1E-4 AND ABS(IM(Y))<1E-4 THEN
! LET X=RE(X)
! LET Y=RE(Y)
!ELSE
! PRINT "ERROR!!"
! STOP
!END IF
!IF X<>0 THEN
! LET TH=ATN(Y/X)
! IF Y<>0 THEN
! IF X>0 AND Y<0 THEN LET TH=TH+PI*2
! IF X<0 THEN LET TH=TH+PI
! ELSE
! IF X<0 THEN LET TH=PI ELSE LET TH=0
! END IF
!ELSE
! LET TH=PI/2
! IF Y<0 THEN LET TH=TH+PI
!END IF
!LET ATAN2=TH
!END FUNCTION
EXTERNAL SUB HORNER(X(),Y(),K())
MAT Y=ZER
LET Y(0)=K(MAXLEVEL)
FOR I=MAXLEVEL-1 TO 0 STEP -1
CALL CMUL2(Y,X)
LET Y(0)=Y(0)+K(I)
NEXT I
END SUB
EXTERNAL SUB SMUL(A(),N)
MAT A=(N)*A
END SUB
EXTERNAL SUB COPY(A(),B())
MAT A=B
END SUB
EXTERNAL SUB CMUL(A(),B(),C())
OPTION BASE 0
DIM T$(15,15)
MAT C=ZER
MAT READ T$
FOR I=0 TO 15
FOR J=0 TO 15
IF A(I)<>0 AND B(J)<>0 THEN
IF T$(I,J)="-0" THEN
LET C(0)=C(0)-A(I)*B(J)
ELSE
LET D=VAL(T$(I,J))
IF D>=0 THEN
LET C(D)=C(D)+A(I)*B(J)
ELSE
LET C(-D)=C(-D)-A(I)*B(J)
END IF
END IF
END IF
NEXT J
NEXT I
DATA 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15 !'16元数乗積表 (ウィキペディアより)
DATA 1, -0, 3, -2, 5, -4, -7, 6, 9, -8,-11, 10,-13, 12, 15,-14
DATA 2, -3, -0, 1, 6, 7, -4, -5, 10, 11, -8, -9,-14,-15, 12, 13
DATA 3, 2, -1, -0, 7, -6, 5, -4, 11,-10, 9, -8,-15, 14,-13, 12
DATA 4, -5, -6, -7, -0, 1, 2, 3, 12, 13, 14, 15, -8, -9,-10,-11
DATA 5, 4, -7, 6, -1, -0, -3, 2, 13,-12, 15,-14, 9, -8, 11,-10
DATA 6, 7, 4, -5, -2, 3, -0, -1, 14,-15,-12, 13, 10,-11, -8, 9
DATA 7, -6, 5, 4, -3, -2, 1, -0, 15, 14,-13,-12, 11, 10, -9, -8
DATA 8, -9,-10,-11,-12,-13,-14,-15,
-0, 1, 2, 3, 4, 5, 6, 7
DATA 9, 8,-11, 10,-13, 12, 15,-14, -1, -0, -3, 2, -5, 4, 7, -6
DATA 10, 11, 8, -9,-14,-15, 12, 13, -2, 3, -0, -1, -6, -7, 4, 5
DATA 11,-10, 9, 8,-15, 14,-13, 12, -3, -2, 1, -0, -7, 6, -5, 4
DATA 12, 13, 14, 15, 8, -9,-10,-11, -4, 5, 6, 7, -0, -1, -2, -3
DATA 13,-12, 15,-14, 9, 8, 11,-10, -5, -4, 7, -6, 1, -0, 3, -2
DATA 14,-15,-12, 13, 10,-11, 8, 9, -6, -7, -4, 5, 2, -3, -0, 1
DATA 15, 14,-13,-12, 11, 10, -9, 8, -7, 6, -5, -4, 3, 2, -1, -0
END SUB
EXTERNAL SUB CMUL2(A(),B())
OPTION BASE 0
DIM C(15)
CALL CMUL(A,B,C)
CALL COPY(A,C)
END SUB
EXTERNAL SUB CADD(A(),B(),C())
MAT C=A+B
END SUB
EXTERNAL SUB CSUB(A(),B(),C())
MAT C=A-B
END SUB
EXTERNAL SUB CDIV(A(),B(),C())
OPTION BASE 0
DIM BB(15),S(15)
CALL CCONJ(B,BB)
CALL CMUL(B,BB,S)
CALL CMUL(A,BB,C)
CALL SMUL(C,1/S(0))
END SUB
EXTERNAL SUB CCONJ(A(),B())
LET B(0)=A(0)
FOR I=1 TO 15
LET B(I)=-A(I)
NEXT I
END SUB
EXTERNAL SUB CPRINT(A())
FOR I=0 TO 15
IF A(I)<>0 THEN
IF A(I)<0 THEN
PRINT " - ";
ELSE
IF I>0 AND A(0)<>0 THEN PRINT " + ";
END IF
IF ABS(A(I))<>1 OR I=0 THEN PRINT STR$(ABS(A(I)));
IF I>0 THEN PRINT MID$("ijklmnopqrstuvw",I,1);
END IF
NEXT I
PRINT
END SUB
EXTERNAL SUB CSIN(X(),Y())
OPTION BASE 0
DIM V(MAXLEVEL)
CALL SINE(V)
CALL HORNER(X,Y,V)
END SUB
EXTERNAL SUB CCOS(X(),Y())
OPTION BASE 0
DIM V(MAXLEVEL)
CALL COSINE(V)
CALL HORNER(X,Y,V)
END SUB
EXTERNAL SUB CTAN(X(),Y())
OPTION BASE 0
DIM XX(15),YY(15)
CALL CSIN(X,XX)
CALL CCOS(X,YY)
CALL CDIV(XX,YY,Y)
END SUB
EXTERNAL SUB CEXP(X(),Y())
OPTION BASE 0
DIM V(MAXLEVEL)
CALL EXPON(V)
CALL HORNER(X,Y,V)
END SUB
EXTERNAL SUB CLOG(X(),Y())
OPTION BASE 0
DIM V(MAXLEVEL),A(15),B(15),C(15)
CALL LN(V)
CALL COPY(A,X)
CALL COPY(B,X)
LET A(0)=A(0)-1
LET B(0)=B(0)+1
CALL CDIV(A,B,C)
CALL HORNER(C,Y,V)
CALL SMUL(Y,2)
END SUB
EXTERNAL SUB CPOWER(X(),Y(),A())
OPTION BASE 0
DIM XX(15),YY(15)
CALL COPY(YY,Y)
CALL CLOG(X,XX)
CALL CMUL2(YY,XX)
CALL CEXP(YY,A)
END SUB
EXTERNAL SUB SINE(X())
!'SIN(X)
LET X(1)=1
LET T=1
FOR I=3 TO MAXLEVEL STEP 2
LET T=-T/(I-1)/I
LET X(I)=T
NEXT I
END SUB
EXTERNAL SUB COSINE(X())
!'COS(X)
LET X(0)=1
LET T=1
FOR I=2 TO MAXLEVEL STEP 2
LET T=-T/(I-1)/I
LET X(I)=T
NEXT I
END SUB
EXTERNAL SUB EXPON(X())
!'EXP(X)
LET X(0)=1
LET T=1
FOR I=1 TO MAXLEVEL
LET T=T/I
LET X(I)=T
NEXT I
END SUB
EXTERNAL SUB LN(X())
!'LOG((X-1)/(X+1))
FOR I=1 TO MAXLEVEL
IF MOD(I,2)=1 THEN LET X(I)=1/I
NEXT I
END SUB
OPTION ARITHMETIC COMPLEX
LET N=10 !'探索範囲
DIM P(-N TO N,-N TO N)
FOR X=0 TO N
FOR Y=0 TO N
LET Z=COMPLEX(X,Y)
PRINT Z;":";
LET FL=0
MAT P=ZER
LET P(0,0)=1 !'0,±1,±iは約数(?)ではない
LET P(1,0)=1
LET P(0,1)=1
LET P(-1,0)=1
LET P(0,-1)=1
IF P(RE(Z),IM(Z))=0 THEN
!'IF ISGAUSSIANPRIME(Z)<>0 THEN
!' PRINT "素数";
!'ELSE
FOR A=0 TO N
FOR B=0 TO N
FOR I=1 TO -1 STEP -2
FOR
J=1 TO -1 STEP -2
LET V=COMPLEX(A*I,B*J)
IF V<>0 THEN
LET
S=Z/V
IF
CMOD(Z,V)=0 AND P(RE(S),IM(S))=0 AND P(RE(V),IM(V))=0 THEN
PRINT "{";V;",";S;"}";
LET P(RE(S),IM(S))=1
LET P(RE(V),IM(V))=1
LET FL=1
END
IF
END IF
NEXT J
NEXT I
NEXT B
NEXT A
IF FL=0 THEN PRINT "素数";
!' END IF
END IF
PRINT
NEXT Y
NEXT X
END
EXTERNAL FUNCTION CINT(Z)
OPTION ARITHMETIC COMPLEX
LET CINT=COMPLEX(INT(RE(Z)),INT(IM(Z)))
END FUNCTION
EXTERNAL FUNCTION CMOD(X,Y)
OPTION ARITHMETIC COMPLEX
LET CMOD=X-CINT(X/Y)*Y
END FUNCTION
EXTERNAL FUNCTION ISGAUSSIANPRIME(Z) !'ガウス素数
OPTION ARITHMETIC COMPLEX
LET ISGAUSSIANPRIME=0
LET A = ABS(RE(Z))
LET B = ABS(IM(Z))
IF A = 0 THEN
IF MOD(B, 4) = 3 AND ISPRIME(B)<>0 THEN LET ISGAUSSIANPRIME=-1
END IF
IF B = 0 THEN
IF MOD(A , 4) = 3 AND ISPRIME(A)<>0 THEN LET ISGAUSSIANPRIME=-1
END IF
IF ISPRIME(A*A+B*B)<>0 THEN LET ISGAUSSIANPRIME=-1
END FUNCTION
EXTERNAL FUNCTION ISPRIME(X)
OPTION ARITHMETIC COMPLEX
IF X=0 OR X=1 THEN
LET ISPRIME=0
EXIT FUNCTION
END IF
IF X=2 THEN
LET ISPRIME=-1
EXIT FUNCTION
END IF
IF MOD(X,2)=0 THEN
LET ISPRIME=0
EXIT FUNCTION
END IF
FOR I=3 TO INT(SQR(X)) STEP 2
IF MOD(X,I)=0 THEN
LET ISPRIME=0
EXIT FUNCTION
END IF
NEXT I
LET ISPRIME=-1
END FUNCTION
PUBLIC NUMERIC N
LET N=10 !'探索範囲 (+n+ni+nj+nj+nk..)〜(-n-ni-nj-nj-nk..) (i,j,k...は虚数単位)
DO
READ L
IF L=0 THEN STOP
DATA 2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97
DATA 0
PRINT L;":";
IF CHECK(L)=1 THEN PRINT "素数"
LOOP
END
EXTERNAL FUNCTION CHECK(L) !'オクトニオン(8元数)探索 (8重ループ)
OPTION BASE 0
DIM X(15),Y(15),Z(15)
LET X(0)=L
FOR H=0 TO N
FOR S8=1 TO -1 STEP -2
LET Y(7)=H*S8
FOR G=0 TO N
FOR S7=1 TO -1 STEP -2
LET Y(6)=G*S7
FOR F=0 TO N
FOR S6=1 TO -1 STEP -2
LET Y(5)=F*S6
FOR E=0 TO N
FOR S5=1 TO -1 STEP -2
LET
Y(4)=E*S5
FOR
D=0 TO N
FOR S4=1 TO -1 STEP -2
LET
Y(3)=D*S4
FOR
C=0 TO N
FOR S3=1 TO -1 STEP -2
LET
Y(2)=C*S3
FOR
B=0 TO N
FOR S2=1 TO -1 STEP -2
LET
Y(1)=B*S2
FOR
A=0 TO N
FOR S1=1 TO -1 STEP -2
LET
Y(0)=A*S1
IF
COMP(Y)=0 THEN
CALL CDIV(X,Y,Z)
IF COMP(Z)=0 THEN
LET
FR=0
FOR
I=0 TO 15
IF FRAC(Z(I))<>0 THEN
LET
FR=1
EXIT
FOR
END IF
NEXT
I
IF
FR=0 THEN
PRINT "{";
CALL CPRINT(Y)
PRINT ",";
CALL CPRINT(Z)
PRINT "}"
LET CHECK=0
EXIT FUNCTION !'見つけ次第ループ打ち切り
END
IF
END IF
END
IF
NEXT S1
NEXT A
NEXT S2
NEXT B
NEXT S3
NEXT
C
NEXT S4
NEXT D
NEXT S5
NEXT E
NEXT S6
NEXT F
NEXT S7
NEXT G
NEXT S8
NEXT H
LET CHECK=1
END FUNCTION
EXTERNAL FUNCTION COMP(Y())
OPTION BASE 0
DIM Z(15)
FOR I=1 TO 16
LET FL=0
MAT READ Z
DATA 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 !'0
DATA 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 !'1
DATA -1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
DATA 0, 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0 !'i
DATA 0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0
DATA 0,0, 1,0,0,0,0,0,0,0,0,0,0,0,0,0 !'j
DATA 0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0
DATA 0,0,0, 1,0,0,0,0,0,0,0,0,0,0,0,0 !'k
DATA 0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0
DATA 0,0,0,0, 1,0,0,0,0,0,0,0,0,0,0,0 !'l
DATA 0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0
DATA 0,0,0,0,0, 1,0,0,0,0,0,0,0,0,0,0 !'m
DATA 0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0
DATA 0,0,0,0,0,0, 1,0,0,0,0,0,0,0,0,0 !'n
DATA 0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0
DATA 0,0,0,0,0,0,0, 1,0,0,0,0,0,0,0,0 !'o
DATA 0,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0
!'DATA 0,0,0,0,0,0,0,0, 1,0,0,0,0,0,0,0
!'DATA 0,0,0,0,0,0,0,0,-1,0,0,0,0,0,0,0
!'DATA 0,0,0,0,0,0,0,0,0, 1,0,0,0,0,0,0
!'DATA 0,0,0,0,0,0,0,0,0,-1,0,0,0,0,0,0
!'DATA 0,0,0,0,0,0,0,0,0,0, 1,0,0,0,0,0
!'DATA 0,0,0,0,0,0,0,0,0,0,-1,0,0,0,0,0
!'DATA 0,0,0,0,0,0,0,0,0,0,0, 1,0,0,0,0
!'DATA 0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,0
!'DATA 0,0,0,0,0,0,0,0,0,0,0,0, 1,0,0,0
!'DATA 0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0
!'DATA 0,0,0,0,0,0,0,0,0,0,0,0,0, 1,0,0
!'DATA 0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0
!'DATA 0,0,0,0,0,0,0,0,0,0,0,0,0,0, 1,0
!'DATA 0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0
!'DATA 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 1
!'DATA 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1
FOR J=0 TO 15
IF Y(J)=Z(J) THEN LET FL=FL+1 !'0,±1,±i,±j,±k...は約数(?)ではない
NEXT J
IF FL=16 THEN
LET COMP=1
EXIT FUNCTION
END IF
NEXT I
LET COMP=0
END FUNCTION
EXTERNAL FUNCTION FRAC(X) !'小数部
LET FRAC=X-INT(X)
END FUNCTION
EXTERNAL SUB CDIV(A(),B(),C())
OPTION BASE 0
DIM BB(15),S(15)
CALL CCONJ(B,BB)
CALL CMUL(B,BB,S)
CALL CMUL(A,BB,C)
MAT C=(1/S(0))*C
END SUB
EXTERNAL SUB CCONJ(A(),B()) !'共役数
LET B(0)=A(0)
FOR I=1 TO 15
LET B(I)=-A(I)
NEXT I
END SUB
EXTERNAL SUB CPRINT(A())
FOR I=0 TO 15
IF A(I)<>0 THEN
IF A(I)<0 THEN
PRINT " - ";
ELSE
IF I>0 THEN PRINT " + ";
END IF
IF ABS(A(I))<>1 OR I=0 THEN PRINT STR$(ABS(A(I)));
IF I>0 THEN PRINT MID$("ijklmnopqrstuvw",I,1);
END IF
NEXT I
END SUB
EXTERNAL SUB CMUL(A(),B(),S())
LET
S(0)=A(0)*B(0)-A(1)*B(1)-A(2)*B(2)-A(3)*B(3)-A(4)*B(4)-A(5)*B(5)-A(6)*B(6)-A(7)*B(7)-A(8)*B(8)-A(9)*B(9)-A(10)*B(10)-A(11)*B(11)-A(12)*B(12)-A(13)*B(13)-A(14)*B(14)-A(15)*B(15)
LET
S(1)=A(0)*B(1)+A(1)*B(0)+A(2)*B(3)-A(3)*B(2)+A(4)*B(5)-A(5)*B(4)-A(6)*B(7)+A(7)*B(6)+A(8)*B(9)-A(9)*B(8)-A(10)*B(11)+A(11)*B(10)-A(12)*B(13)+A(13)*B(12)+A(14)*B(15)-A(15)*B(14)
LET
S(2)=A(0)*B(2)-A(1)*B(3)+A(2)*B(0)+A(3)*B(1)+A(4)*B(6)+A(5)*B(7)-A(6)*B(4)-A(7)*B(5)+A(8)*B(10)+A(9)*B(11)-A(10)*B(8)-A(11)*B(9)-A(12)*B(14)-A(13)*B(15)+A(14)*B(12)+A(15)*B(13)
LET
S(3)=A(0)*B(3)+A(1)*B(2)-A(2)*B(1)+A(3)*B(0)+A(4)*B(7)-A(5)*B(6)+A(6)*B(5)-A(7)*B(4)+A(8)*B(11)-A(9)*B(10)+A(10)*B(9)-A(11)*B(8)-A(12)*B(15)+A(13)*B(14)-A(14)*B(13)+A(15)*B(12)
LET
S(4)=A(0)*B(4)-A(1)*B(5)-A(2)*B(6)-A(3)*B(7)+A(4)*B(0)+A(5)*B(1)+A(6)*B(2)+A(7)*B(3)+A(8)*B(12)+A(9)*B(13)+A(10)*B(14)+A(11)*B(15)-A(12)*B(8)-A(13)*B(9)-A(14)*B(10)-A(15)*B(11)
LET
S(5)=A(0)*B(5)+A(1)*B(4)-A(2)*B(7)+A(3)*B(6)-A(4)*B(1)+A(5)*B(0)-A(6)*B(3)+A(7)*B(2)+A(8)*B(13)-A(9)*B(12)+A(10)*B(15)-A(11)*B(14)+A(12)*B(9)-A(13)*B(8)+A(14)*B(11)-A(15)*B(10)
LET
S(6)=A(0)*B(6)+A(1)*B(7)+A(2)*B(4)-A(3)*B(5)-A(4)*B(2)+A(5)*B(3)+A(6)*B(0)-A(7)*B(1)+A(8)*B(14)-A(9)*B(15)-A(10)*B(12)+A(11)*B(13)+A(12)*B(10)-A(13)*B(11)-A(14)*B(8)+A(15)*B(9)
LET
S(7)=A(0)*B(7)-A(1)*B(6)+A(2)*B(5)+A(3)*B(4)-A(4)*B(3)-A(5)*B(2)+A(6)*B(1)+A(7)*B(0)+A(8)*B(15)+A(9)*B(14)-A(10)*B(13)-A(11)*B(12)+A(12)*B(11)+A(13)*B(10)-A(14)*B(9)-A(15)*B(8)
LET
S(8)=A(0)*B(8)-A(1)*B(9)-A(2)*B(10)-A(3)*B(11)-A(4)*B(12)-A(5)*B(13)-A(6)*B(14)-A(7)*B(15)+A(8)*B(0)+A(9)*B(1)+A(10)*B(2)+A(11)*B(3)+A(12)*B(4)+A(13)*B(5)+A(14)*B(6)+A(15)*B(7)
LET
S(9)=A(0)*B(9)+A(1)*B(8)-A(2)*B(11)+A(3)*B(10)-A(4)*B(13)+A(5)*B(12)+A(6)*B(15)-A(7)*B(14)-A(8)*B(1)+A(9)*B(0)-A(10)*B(3)+A(11)*B(2)-A(12)*B(5)+A(13)*B(4)+A(14)*B(7)-A(15)*B(6)
LET
S(10)=A(0)*B(10)+A(1)*B(11)+A(2)*B(8)-A(3)*B(9)-A(4)*B(14)-A(5)*B(15)+A(6)*B(12)+A(7)*B(13)-A(8)*B(2)+A(9)*B(3)+A(10)*B(0)-A(11)*B(1)-A(12)*B(6)-A(13)*B(7)+A(14)*B(4)+A(15)*B(5)
LET
S(11)=A(0)*B(11)-A(1)*B(10)+A(2)*B(9)+A(3)*B(8)-A(4)*B(15)+A(5)*B(14)-A(6)*B(13)+A(7)*B(12)-A(8)*B(3)-A(9)*B(2)+A(10)*B(1)+A(11)*B(0)-A(12)*B(7)+A(13)*B(6)-A(14)*B(5)+A(15)*B(4)
LET
S(12)=A(0)*B(12)+A(1)*B(13)+A(2)*B(14)+A(3)*B(15)+A(4)*B(8)-A(5)*B(9)-A(6)*B(10)-A(7)*B(11)-A(8)*B(4)+A(9)*B(5)+A(10)*B(6)+A(11)*B(7)+A(12)*B(0)-A(13)*B(1)-A(14)*B(2)-A(15)*B(3)
LET
S(13)=A(0)*B(13)-A(1)*B(12)+A(2)*B(15)-A(3)*B(14)+A(4)*B(9)+A(5)*B(8)+A(6)*B(11)-A(7)*B(10)-A(8)*B(5)-A(9)*B(4)+A(10)*B(7)-A(11)*B(6)+A(12)*B(1)+A(13)*B(0)+A(14)*B(3)-A(15)*B(2)
LET
S(14)=A(0)*B(14)-A(1)*B(15)-A(2)*B(12)+A(3)*B(13)+A(4)*B(10)-A(5)*B(11)+A(6)*B(8)+A(7)*B(9)-A(8)*B(6)-A(9)*B(7)-A(10)*B(4)+A(11)*B(5)+A(12)*B(2)-A(13)*B(3)+A(14)*B(0)+A(15)*B(1)
LET
S(15)=A(0)*B(15)+A(1)*B(14)-A(2)*B(13)-A(3)*B(12)+A(4)*B(11)+A(5)*B(10)-A(6)*B(9)+A(7)*B(8)-A(8)*B(7)+A(9)*B(6)-A(10)*B(5)-A(11)*B(4)+A(12)*B(3)+A(13)*B(2)-A(14)*B(1)+A(15)*B(0)
END SUB
> kikiririさんへのお返事です。
>
> 参考サイト http://hw001.gate01.com/kazuok/geodetic/leveling.html
>
> Full BASICの場合、行列が計算できるので、他の言語よりは簡単に計算できると思います。
> ただ、2項演算までですから、展開しながらこつこつ計算する必要があります。
>
> また、表計算の方がGUIを含めて実用化し易いかもしれません。
>
>
> 上記サイトの例題(PDFファイル内)のサンプルコーディング
>
> <PRE>
> !最小2乗法による測量網平均(条件方程式法)
>
> !H型
> ! A C
> ! 1↓ 5 ↓3
> ! P → Q
> ! 2↑ ↑4
> ! B D
>
> !既知点
> LET C=4 !数
>
> DATA 25.645 !A点の標高(m)
> DATA 24.666 !B点
> DATA 25.024 !C点
> DATA 25.699 !D点
> DIM Z(C)
> MAT READ Z
>
> !観測値
> LET P=5 !数
>
> DATA -6.225, 0.44 !路線1 高低差(m)、路線長(km)
> DATA -5.245, 0.25 !路線2
> DATA 0.278, 0.33 !路線3
> DATA -0.399, 0.26 !路線4
> DATA 5.879, 0.44 !路線5
>
> DIM X(P),G(P,P) !観測値、コアファクタ
> MAT G=ZER
> FOR i=1 TO P
> READ X(i),G(i,i)
> NEXT i
> MAT PRINT X;
> MAT PRINT G;
>
>
> !未知数
> LET Px=2 !求点PとQ
>
>
> !------------------------------
>
> !自由度R ※条件方程式の数
> LET R=P-Px
>
>
> !条件方程式 UV=t
> DIM U(R,P)
> DATA 1,-1,0,0,0 !点Pについて HA+h1~=HB+h2~ より、(h1+v1)-(h2+v2)=HB-HA ∴v1-v2=-(h1+HA)+(h2+HB)
> DATA 0,0,1,-1,0 !点Qについて HC+h3~=HD+h4~
> DATA 1,0,0,-1,1 !点Pと点Qについて HA+h1~+h5~=HD+h4~
> MAT READ U
>
> DIM t(R,1)
> FOR i=1 TO R
> LET s=0
> FOR j=1 TO P
> IF j>C THEN LET Zj=0 ELSE LET Zj=Z(j)
> LET s=s-(X(j)+Zj)*U(i,j)
> NEXT j
> LET t(i,1)=s
> NEXT i
> !!!LET t(1,1)=-X(1)+X(2)-Z(1)+Z(2) !0.001
> !!!LET t(2,1)=-X(3)+X(4)-Z(3)+Z(4) !-0.002
> !!!LET t(3,1)=-X(1)+X(4)-X(5)-Z(1)+Z(4) !0.001
> MAT PRINT t;
>
>
> !------------------------------
>
> !相関式 NK=t、N=UG(Ut)より、K=(Ni)tを求める
> DIM Ut(P,R)
> MAT Ut=TRN(U)
> DIM TMP(P,R) !G(Ut) ※次でも使う
> MAT TMP=G*Ut
> DIM N(R,R)
> MAT N=U*TMP
> MAT PRINT N;
>
> DIM invN(R,R)
> MAT invN=INV(N)
> DIM K(R,1)
> MAT K=invN*t
>
> MAT PRINT K;
>
>
> !補正値の計算(mm) V=G(Ut)K
> DIM V(P,1)
> MAT V=TMP*K
>
> MAT PRINT V;
>
>
> !最確値 X~=X+V
> FOR i=1 TO P
> PRINT "路線";STR$(i);"=";X(i)+V(i,1)
> NEXT i
> PRINT "点P";Z(1)+(X(1)+V(1,1)); Z(2)+(X(2)+V(2,1)) !有効桁数 ##.###
> PRINT "点Q";Z(3)+(X(3)+V(3,1)); Z(4)+(X(4)+V(4,1))
>
>
>
>
> !精度の計算(mm^2) σ^2=(Kt)NK/r
> DIM s2(1,1),Kt(1,R)
> MAT Kt=TRN(K)
> MAT s2=Kt*t !NK=t
> LET sigma2=s2(1,1)/R
>
> PRINT "σ^2=";sigma2
>
>
> !分散行列(mm^2) σ^2*Gx、Gx=G-G(Ut)(Ni)UG
> DIM Gx(P,P)
> MAT Gx=TMP*invN !G(Ut)(Ni)
> MAT Gx=Gx*U
> MAT Gx=Gx*G
> MAT Gx=G-Gx
> MAT Gx=sigma2*Gx
>
> MAT PRINT Gx;
>
>
> END
> </PRE>
100 SET WINDOW 2,10,5,13
!SET WINDOW -4,4,-4,4
!SET WINDOW -3,5,4,12
110 LET a=1 ! a=.425
120 LET b=1
130 DRAW AXES(a,b)
!DRAW AXES0(a,b)
!DRAW GRID(a,b)
!DRAW GRID0(a,b) ! 組込み絵定義
140 END
REM ** 座標数字位置自動調整 **
EXTERNAL PICTURE AXES(p,q)
DRAW axes_grid("on","ax",STR$(p),STR$(q))
END PICTURE
EXTERNAL PICTURE AXES0(p,q)
DRAW axes_grid("off","ax",STR$(p),STR$(q))
END PICTURE
EXTERNAL PICTURE GRID(p,q)
DRAW axes_grid("on","gr",STR$(p),STR$(q))
END PICTURE
!
!十進BASIC添付"\BASICw32\Library\Grid2.lib"参照
! num$="off"数字無,"on"数字有 , ag$="ax"軸,"gr"格子 , sx=x軸目盛間隔 , sy=y軸目盛間隔
EXTERNAL PICTURE axes_grid(num$,ag$,sx$,sy$)
OPTION ARITHMETIC DECIMAL
FUNCTION val_r(f$) ! 有理数を小数に変換
LET vrp=POS(f$,"/")
IF vrp=0 THEN LET val_r=VAL(f$) ELSE LET val_r=VAL(f$(1:vrp-1))/VAL(f$(vrp+1:LEN(f$)))
END FUNCTION
FUNCTION round_cut$(a$,A,s) ! 小数桁カット
ASK TEXT WIDTH(a$) w
LET d=LEN(a$)
LET p=POS(a$,".")
IF w>s AND p>0 AND
POS(a$,"E")=0 AND d>2 AND NOT(d=3 AND a$(1:2)="-." OR a$(d:d)=".")
THEN
LET a$=STR$(SGN(A)*ROUND(ABS(A),d-p-1))
! LET a$=STR$(ROUND(A,d-p-1))
IF
POS(a$,".")>0 THEN LET a$=a$&"00000000" ELSE LET
a$=a$&".00000000"
LET a$=round_cut$(a$(1:d-1),A,s)
END IF
LET round_cut$=a$
END FUNCTION
LET sx=val_r(sx$)
LET sy=val_r(sy$)
ASK WINDOW L,R,B,T
ASK LINE STYLE S
ASK LINE COLOR C
SET LINE COLOR 15 ! 銀色
ASK TEXT COLOR TC
SET TEXT COLOR 15 ! 銀色
ASK TEXT JUSTIFY ts1$,ts2$
SET LINE STYLE 1
PLOT LINES:L,0;R,0 ! x軸
PLOT LINES:0,B;0,T ! y軸
IF ag$="gr" THEN SET LINE STYLE 3
IF sx<>0 THEN
IF B*T<0 OR T=0 THEN SET TEXT
JUSTIFY "RIGHT","TOP" ELSE SET TEXT JUSTIFY "RIGHT","BOTTOM"
IF B*T<0 OR T=0 THEN LET y0=0 ELSE LET y0=B
LET wy=WORLDY(PIXELY(0)+2)
LET n=ABS(INT(LOG10(sx)-2))
FOR X=CEIL(L/sx)*sx TO INT(R/sx)*sx+1.001*sx STEP sx
IF ag$="gr" THEN PLOT LINES:X,B;X,T ELSE PLOT LINES:X,-wy;X,wy
IF y0=B AND ag$="ax" THEN
PLOT LINES:X,B-(T-B)/100;X,WORLDY(3) ! 下端目盛線
PLOT LINES:X,T+(T-B)/100;X,WORLDY(PIXELY(T)-3) ! 上端目盛線
END IF
IF
num$="on" THEN PLOT TEXT,AT X,y0 : round_cut$(STR$(ROUND(X,n)),X,sx)
NEXT X
END IF
IF sy<>0 THEN
IF L*R<0 OR R=0 THEN SET TEXT JUSTIFY "RIGHT","TOP" ELSE SET TEXT JUSTIFY "LEFT","TOP"
IF L*R<0 OR R=0 THEN LET x0=0 ELSE LET x0=L
LET wx=WORLDX(PIXELX(0)+2)
LET n=ABS(INT(LOG10(sy)-2))
FOR Y=CEIL(B/sy)*sy TO INT(T/sy)*sy+1.001*sy STEP sy
IF ag$="gr" THEN PLOT LINES:L,Y;R,Y ELSE PLOT LINES:-wx,Y;wx,Y
IF x0=L AND ag$="ax" THEN
PLOT LINES:L-(R-L)/100,Y;WORLDX(3),Y ! 左端目盛線
PLOT LINES:R+(R-L)/100,Y;WORLDX(PIXELX(R)-3),Y ! 右端目盛線
END IF
IF num$="on" THEN PLOT TEXT,AT x0,Y : STR$(ROUND(Y,n))
NEXT Y
END IF
SET TEXT JUSTIFY "RIGHT","TOP"
IF num$="on" AND sx=0 AND sy=0 THEN PLOT TEXT,AT 0,0:STR$(0)
SET LINE COLOR C
SET LINE STYLE S
SET TEXT COLOR TC
SET TEXT JUSTIFY ts1$,ts2$
END PICTURE
!最小2乗法による測量網平均(観測方程式)
!参考文献 最小ニ乗法と測量網平均の基礎 東洋出版 p.170〜173(p.165〜177)
!既知点
LET H301=41.7065 !301点の標高(m)
LET H302=43.9632 !302点
!観測値
LET n=6 !数
DATA 5.1342, 4.6 !路線1 観測比高(高低差)(m)、路線距離(km)
DATA -2.0508, 5.2 !路線2
DATA -2.2287, 9.2 !路線3
DATA -0.0330, 6.3 !路線4
DATA -0.8601, 3.9 !路線5
DATA -0.8258, 8.3 !路線6
DIM Hb(n),P(n,n) !観測値、重量行列
MAT P=ZER
FOR i=1 TO n
READ Hb(i),Wi
LET P(i,i)=1/Wi
NEXT i
MAT PRINT Hb; !debug
MAT PRINT P; !debug
!新点(未知点)
LET m=3 !数
LET pnt$="123"
!------------------------------ 観測方程式の一般式 V=A*X+Lを組み立てる p.170〜171
DIM A(n,m) !係数行列 ※各路線の観測比高と新点標高との関係より
DATA -1, 1, 0
DATA 0,-1, 0
DATA 0, 0, 1
DATA 0, 0,-1
DATA 1, 0,-1
DATA 1, 0, 0
MAT READ A
DIM L(n,1) !定数項
LET L(1,1)=-Hb(1)
LET L(2,1)=-(Hb(2)-H302)
LET L(3,1)=-(H302+Hb(3))
LET L(4,1)=-(Hb(4)-H301)
LET L(5,1)=-Hb(5)
LET L(6,1)=-(H301+Hb(6))
MAT PRINT A; !debug
MAT PRINT L; !debug
!------------------------------ 方程式の解(X~)を求める p.172中
DIM TT(50,50),MM(50,50) !作業用
MAT TT=TRN(A) !TRN(A)*P*Aの計算
MAT TT=TT*P
MAT MM=TT !save it
MAT TT=TT*A
MAT PRINT TT; !debug
DIM Q(m,m) !重み係数行列 Q=INV(TRN(A)*P*A)の計算
MAT Q=INV(TT)
MAT PRINT Q; !debug
MAT TT=MM*L !TRN(A)*P*Lの計算
MAT PRINT TT; !debug
DIM Xb(m,1) !最確値 X~
MAT TT=Q*TT
MAT Xb=(-1)*TT
MAT PRINT Xb; !debug
!------------------------------ 網平均の最終結果 p.172中〜173
DIM Vb(n,1) !残差ベクトル V~=L-A*INV(TRN(A)*P*A)*TRN(A)*P*Lの計算
MAT TT=A*Xb !Xb=-INV(TRN(A)*P*A)*TRN(A)*P*Lより
MAT Vb=L+TT
MAT PRINT Vb; !debug
MAT TT=TRN(Vb) !単位重みの標準偏差σ0の推定値 m0=SQR(TRN(V~)*P*V~/(m-n))の計算
MAT TT=TT*P
MAT TT=TT*Vb
MAT PRINT TT; !debug
LET m0=SQR(TT(1,1)/(n-m))
PRINT "m0="; m0 !debug
FOR i=1 TO m
PRINT pnt$(i:i); "点の標高"; Xb(i,1);"m"; !有効桁数 ##.####
PRINT " ±"; m0*SQR(Q(i,i)); "mm" !有効桁数 #.#
NEXT i
END
!DQT
SUB FFDB
DO WHILE 0< N
CALL RED_D
LET w= IP(ORD(D$)/16) !p=0(byte) p=1(word)
LET J=MOD(ORD(D$),16) !J=0~3 (QT.number)
FOR i=0 TO 63
CALL RED_D
LET DQ(U(i),V(i),J)=ORD(D$)
IF w=1 THEN
CALL RED_D
LET DQ(U(i),V(i),J)=DQ(U(i),V(i),J)*256+ORD(D$)
END IF
NEXT i
LET N=N-65-64*w ! remain size
LOOP
END SUB
!SOF0
SUB FFC0
CALL RED_D
IF ORD(D$)<>8 THEN BREAK ! 8bit( 24bitColor ) at RGB.dimension
CALL RED_D
LET W=ORD(D$)*256
CALL RED_D
LET DY=W+ORD(D$) !V.pix.
CALL RED_D
LET W=ORD(D$)*256
CALL RED_D
LET DX=W+ORD(D$) !H.pix.
CALL RED_D
FOR i=0 TO ORD(D$)-1 !1~3 scan order items
CALL RED_D
LET CoID(ORD(D$))=i ! (Y=0, Cb=1, Cr=2)<-- CoID( ID=0~255)
CALL RED_D
LET MH(i)= IP(ORD(D$)/16) ! HV Y=11,12,21,22,41 Cb=11,11,11,11,11 Cr=11,11,11,11,11
LET MV(i)=MOD(ORD(D$),16)
CALL RED_D
LET QS(i)=ORD(D$) ! QT.number0~3 <-- QS( Y=0, Cb=1, Cr=2)
NEXT i
IF 2< i THEN LET CMO=2 ELSE LET CMO=0
END SUB
!DHT
SUB FFC4
DO WHILE 0< N
CALL RED_D
LET
J=ORD(D$) !
0?~1?=DC~AC ?0~?3=ID0~ID3
LET J=2*MOD(J,16)+IP(J/16) ! 0~1=ID0.DC~AC 2~3=ID1.DC~AC 4~5=ID2.…
LET DH(0,J)=0 !!!for 2nd.use for clear
FOR i=1 TO 16
CALL RED_D
LET DH(i,J)=ORD(D$)
LET DH(0,J)=DH(0,J)+DH(i,J)
NEXT i
FOR i=0 TO DH(0,J)-1
CALL RED_D
LET DV(i,J)=ORD(D$)
NEXT i
!---
FOR i=i TO 255
LET DV(i,J)=0
NEXT i
CALL makeH0(J) ! make Huffman Code table B() L()
CALL makeD0(J) ! make Huffman Decorder table A()
!---
LET N=N-1-16-DH(0,J) ! remain size
LOOP
END SUB
!SOS
SUB FFDA
CALL RED_D
LET M2=ORD(D$)
MAT HDC=(-2)*CON
MAT HAC=(-2)*CON
FOR i=1 TO M2
CALL RED_D
LET w=ORD(D$) !ID=0~255( normal 01~03)
CALL RED_D ! 00=Y 11=Cb 11=Cr
LET HDC(CoID(w))= IP(ORD(D$)/16)*2 !DC 0~3-->0,2,4,6
LET HAC(CoID(w))=MOD(ORD(D$),16)*2+1 !AC 0~3-->1,3,5,7
NEXT i
CALL RED_D
LET Ss_=ORD(D$) ! low of spectral selection
CALL RED_D
LET Se_=ORD(D$) ! high of spectral selection
CALL RED_D
LET Al=MOD(ORD(D$),16) ! low bit of successive approximation
LET Ah=IP(ORD(D$)/16) !high bit of successive approximation
!--- private controll M3(display timing)
LET w=Ah-Al
IF w=0 THEN LET w=1
FOR i=0 TO 2
IF 0<=HAC(i) THEN LET M3(i)=M3(i)+(Se_-Ss_+1)*w ! M3()= scan band sum
NEXT i
!--- next image data top
END SUB
SUB ROPEN
OPEN #1 :NAME FL$ ,ACCESS INPUT
END SUB
SUB RED_D
CHARACTER INPUT #1 :D$
LET byt=byt+1 !!!
END SUB
!============
! B(,J)L(,J)<-- DH(,J) for decorder table A(,J)
!
SUB makeH0(J)
LET i=0 ! コード生成 順番(短い順)
LET Hx=0
LET Tx=BVAL("8000",16)
FOR L_=1 TO 16
FOR P=1 TO DH(L_,J)
LET L(i,J)=L_
LET B(i,J)=Hx ! コード(生成順), 座標DV(頻度降順) と同順。
LET i=i+1
LET Hx=Hx+Tx
NEXT P
LET Tx=Tx/2
NEXT L_
LET B(256,J)=0
FOR i=i TO 255
LET L(i,J)=0
LET B(i,J)=0
NEXT i
END SUB
!============
!A(,J)=output decorder table<-- B(,J) L(,J) DH(,J) DV(,J)
!
SUB makeD0(J)
FOR LH=16 TO 1 STEP -1
IF DH(LH,J)<>0 THEN EXIT FOR
NEXT
LH
!length max. in huffman table
LET LM=CEIL(LH/BST)*BST !length max. bound by BST
!---
LET I=0 !start huffman table adr.
LET LA=0 !line adr.
LET P=BST !start Decord code width
LET U_=2^(16-BST) !start Decord code step
LET NC=0 !next start Decord code
DO
LET D_=NC !start Decord code
LET NC=-1
LET LB=LA+(65536-D_)/U_ !1st nest adr.
DO
CALL SERCH
IF 0< L_ THEN
LET
A(LA,J)= BVAL("8000",16)+L_*256+DV(I,J) !b15=end. +L.+V.
ELSEIF P=LM THEN
LET
A(LA,J)= BVAL("C000",16)+LH*256 !b15=end. b14=Unused. +L.
ELSE
IF NC=-1 THEN LET NC=D_
LET A(LA,J)=LB ! nest adr.
LET LB=LB+SHb ! next nest adr.
END IF
LET D_=D_+U_
LET LA=LA+1
LOOP UNTIL IP(D_)=65536
LET P=P+BST
LET U_=U_/SHb !shr(U_,BST)
LOOP UNTIL P>LM
!---
FOR LA=LA TO 255
LET A(LA,J)=0 !(0),table stop mark
NEXT LA
END SUB
SUB SERCH
FOR I=I TO DH(0,J)-1
LET L_=L(I,J)
IF L_<=P THEN LET w=IP(D_/2^(16-L_))*2^(16-L_) ELSE EXIT FOR
IF w<=B(I,J) THEN
IF w=B(I,J) THEN EXIT SUB ELSE EXIT FOR
END IF
NEXT I
LET L_=-1
END SUB
!===========
! Inverse Fast Cosin Transform.( 8x8, iDCT-2 ) ← Inverse Quantization.DQ()
SUB IDDCT8X8
FOR V0=0 TO DV_-1 STEP 8
FOR U0=0 TO DU-1 STEP 8
FOR P=0 TO CMO ! =0(mono) =2(color)
FOR V_=0 TO 7
FOR U_=0 TO 7
LET
X(U_)=D2(U0+U_,V0+V_,P) *DQ(U_,V_,QS(P)) ! Inverse Quantization
NEXT U_
CALL IWANG
FOR X_=0 TO 7
LET T(X_,V_)=X(X_)
NEXT X_
NEXT V_
FOR X_=0 TO 7
FOR V_=0 TO 7
LET X(V_)=T(X_,V_)
NEXT V_
CALL IWANG
FOR Y_=0 TO 7
IF
P=0 THEN LET D1(U0+X_,V0+Y_,P)=X(Y_)+128 ELSE LET
D1(U0+X_,V0+Y_,P)=X(Y_)
NEXT Y_
NEXT X_
NEXT P
NEXT U0
NEXT V0
END SUB
!----inverse Wang.( 8, iDCT-2 )
SUB IWANG
LET XO(0)=SQR(2/8)*X(0)
LET XO(1)=SQR(2/8)*X(4)
LET XO(2)=SQR(2/8)*X(2)
LET XO(3)=SQR(2/8)*X(6)
LET XO(4)=SQR(1/8)*X(1)
LET XO(5)=SQR(1/8)*X(5)
LET XO(6)=SQR(1/8)*X(3)
LET XO(7)=SQR(1/8)*X(7)
!
LET X(4)=(COS(PI /16)*XO(4)+SIN(PI /16)*XO(7))
LET X(5)=(COS(PI*5/16)*XO(5)+SIN(PI*5/16)*XO(6))
LET X(6)=(SIN(PI*5/16)*XO(5)-COS(PI*5/16)*XO(6))
LET X(7)=(SIN(PI /16)*XO(4)-COS(PI /16)*XO(7))
!
LET XO(4)= X(4)+X(5)
LET XO(5)= X(4)-X(5)
LET XO(6)=-X(6)+X(7)
LET XO(7)= X(6)+X(7)
!
LET X(0)=(COS(PI/4)*XO(0)+COS(PI /4)*XO(1))
LET X(1)=(COS(PI/4)*XO(0)-COS(PI /4)*XO(1))
LET X(2)=(SIN(PI/8)*XO(2)-SIN(PI*3/8)*XO(3))
LET X(3)=(COS(PI/8)*XO(2)+COS(PI*3/8)*XO(3))
LET X(4)=XO(4)
LET X(5)=XO(6)
LET X(6)=XO(5)
LET X(7)=XO(7)
!
LET XO(0)=X(0)+X(3)
LET XO(1)=X(1)+X(2)
LET XO(2)=X(1)-X(2)
LET XO(3)=X(0)-X(3)
LET XO(4)=X(7)*SQR(2)
LET XO(5)=X(6)-X(5)
LET XO(6)=X(6)+X(5)
LET XO(7)=X(4)*SQR(2)
!
LET X(0)=XO(0)+XO(7)
LET X(1)=XO(1)+XO(6)
LET X(2)=XO(2)+XO(5)
LET X(3)=XO(3)+XO(4)
LET X(4)=XO(3)-XO(4)
LET X(5)=XO(2)-XO(5)
LET X(6)=XO(1)-XO(6)
LET X(7)=XO(0)-XO(7)
END SUB
!=============
SUB R_BIN31(M) ! decord(M) before new.search(M)
DO
IF M=BVAL("D8",16) THEN ! SOI
MAT DH=ZER ! clear Huffman Table
LET
DRI=0 ! clear Restart Interval.value for
RST0~7(restart marker)
LET rct=-1
! Interval.counter, valid (0<=rct), invalid (rct< 0)
MAT M3=ZER ! clear scan band sum
ELSEIF M=BVAL("D9",16) THEN ! EOI
EXIT DO ! close & end_sub
ELSEIF BVAL("D0",16)<=M AND M<=BVAL("D7",16) THEN ! RST0~7( restart marker)
LET rct=DRI ! set counter with Restart Interval
EXIT SUB
ELSEIF 0< M THEN !M=0 is data"FF" in picture area
CALL RED_D
LET N=ORD(D$)*256
CALL RED_D
LET N=N+ORD(D$)-2 ! N=remain size
!---
IF BVAL("E0",16)<=M AND M<=BVAL("EF",16) THEN ! APP0~APP15
CALL FFE0
ELSEIF M=BVAL("DD",16) THEN
CALL FFDD ! DRI load DRI & rct=DRI
ELSEIF M=BVAL("FE",16) THEN
CALL FFFE ! COMMENT
ELSEIF M=BVAL("C4",16) THEN
CALL FFC4 ! DHT
ELSEIF M=BVAL("DB",16) THEN
CALL FFDB ! DQT
ELSEIF M=BVAL("C0",16) OR M=BVAL("C2",16) THEN
CALL FFC0 ! SOF0 SOF2
ELSEIF M=BVAL("DA",16) THEN
CALL FFDA ! SOS
EXIT SUB ! without close
ELSE
BREAK ! new marker
END IF
END IF
!---
DO
LET M=BVAL("D9",16) ! EOI, 256 ! end of file
CHARACTER INPUT #1,IF MISSING THEN EXIT DO :D$
LET byt=byt+1 !!!
LET M=ORD(D$)
LOOP UNTIL M=255 ! 1st.mark
IF M<>255 THEN EXIT DO ! close & end_sub
CALL RED_D
LET M=ORD(D$)
LOOP
CLOSE #1
END SUB
!DRI
SUB FFDD
CALL RED_D
LET DRI=ORD(D$)*256
CALL RED_D
LET DRI=DRI+ORD(D$)
LET rct=DRI
END SUB
!APP0
SUB FFE0
FOR W=1 TO N
CALL RED_D
NEXT W
END SUB
!COMMENT
SUB FFFE
FOR W=1 TO N
CALL RED_D
NEXT W
END SUB
SUB frame
PRINT " Ss Se AhAl: ";Ss_;Se_;STR$(Ah);STR$(Al)
PRINT " Y HDC HAC: ";IP(HDC(0)/2);IP(HAC(0)/2)
PRINT " Cb : ";IP(HDC(1)/2);IP(HAC(1)/2)
PRINT " Cr : ";IP(HDC(2)/2);IP(HAC(2)/2)
CALL reset0
!---
FOR V09=0 TO DV_-1 STEP 8*MV(0)
FOR U09=0 TO DU-1 STEP 8*MH(0)
IF rct=0 THEN
CALL
R_BIN31(0) ! read marker
IF rct<>DRI THEN BREAK ! not RST0~7
CALL reset0 ! Restart
END IF
CALL MCUxx11 ! read picture data
LET rct=rct-1
!---
IF 0< ext THEN
IF ext=103001 THEN
PRINT "abort marker ";BSTR$(M,16)
IF BVAL("D0",16)<=M AND M<=BVAL("D7",16) THEN ! RST0~7( restart
marker)
LET
rct=DRI ! set counter
CALL
reset0 ! Restart
ELSE
EXIT
SUB ! others marker
END IF
ELSE
PRINT "file error. display fragment"
LET M=BVAL("D9",16) ! EOI
EXIT SUB
END IF
END IF
NEXT U09
NEXT V09
IF 0< EOB THEN PRINT "EOBn over frame";EOB !!!
END SUB
SUB MCUxx11
!---read MCU
FOR P=0 TO CMO
IF 0<=HDC(P) OR 0<=HAC(P) THEN
FOR V0=V09 TO V09+8*MV(P)-1 STEP 8
FOR U0=U09 TO U09+8*MH(P)-1 STEP 8
WHEN EXCEPTION IN
IF
EOB=0 THEN CALL R_BLK0 ELSE LET EOB=EOB-1
USE
LET ext=EXTYPE
EXIT SUB
END WHEN
!---extend bitmap
IF 0< Ah AND 0< Se_ THEN
FOR i=A_ TO Se_
IF D2(U0+U(i),V0+V(i),P)<>0 THEN
LET
L_=1
WHEN
EXCEPTION IN
CALL DEC1_EX
USE
LET ext=EXTYPE
EXIT SUB
END
WHEN
LET
V_=SGN(D2(U0+U(i),V0+V(i),P))*V_*2^Al
LET
D2(U0+U(i),V0+V(i),P)=D2(U0+U(i),V0+V(i),P) +V_
END IF
NEXT i
LET A_=Ss_
END IF
!---
NEXT U0
NEXT V0
END IF
NEXT P
END SUB
!------
SUB R_BLK0
IF Ss_=0 THEN
!---D.C.part
LET debug$="DC.huffman" !!!
IF Ah=0 THEN !-----baseline.progSS.progSA(1st.scan).
LET J=HDC(P) !huffman D.C.table selection P( 0=Y 1=Cb 2=Cr)
CALL DEC1_NS
LET EL=V_ !extent length
!---D.C.extent
LET debug$="DC.huffman extend" !!!
IF 0< EL THEN
LET L_=EL
CALL
DEC1_EX !keep EL, V_=extent value( length EL bits)
LET
W=2^(EL-1) !minimum
in EL bits length
IF V_< W THEN LET V_=V_-(W*2-1) !restore signed value
LET
B2(P)=B2(P)+V_*2^Al !point
transform, integrate to D.C.
END IF
LET D2(U0+U(0),V0+V(0),P)=B2(P)
ELSE !-----progSA(2st.scan).
LET L_=1
CALL DEC1_EX
LET V_=SGN(D2(U0+U(0),V0+V(0),P))*V_
LET D2(U0+U(0),V0+V(0),P)=D2(U0+U(0),V0+V(0),P) +V_*2^Al
END IF
LET Sa_=1
ELSE
LET Sa_=Ss_
END IF
!---A.C.parts
IF Se_=0 THEN EXIT SUB !band Ss_~Se_
LET
J=HAC(P) !huffman
A.C.table selection P( 0=Y 1=Cb 2=Cr)
LET debug$="AC.huffman"
FOR A_=Sa_ TO Se_
CALL DEC1_NS
LET EL=MOD(V_,16) !extent length
LET RL= IP(V_/16) !run length
!---
IF RL<=14 AND EL=0 THEN !End Of Block(00). End Of Band(10,20,,E0)
!---EOBn extend
LET debug$="eobn extend"& STR$(RL)
IF 0< RL THEN
LET
L_=RL !extend=
run_length
CALL
DEC1_EX !keep RL, V_=run value(
length RL bits)
LET EOB=V_+2^RL-1 !RL= End Of Band(10,20,,E0) run length
END IF
EXIT SUB
!---
END IF
!---RL=(0~15)EL=(1~10), RL=(15)EL=(0)
LET debug$="AC.huffman extend" !!!
IF Ah=0 THEN !-----baseline.progSS.progSA(1st.scan).
LET
A_=A_+RL !skip
zero_run_length 0~15
!---A.C.extent
IF 0< EL THEN !ZRL(16) only skip
LET L_=EL
CALL
DEC1_EX !keep EL, V_=extent value( length EL
bits)
LET
w=2^(EL-1) !minimum
in EL bits length
IF V_< w THEN LET V_=V_-(w*2-1) !restore signed value
!---
LET V_=V_*2^Al !point transform
LET D2(U0+U(A_),V0+V(A_),P)=V_
END IF
ELSE !-----progSA(2st.scan).
IF 0< EL THEN !ZRL(16) only skip
LET L_=EL
CALL
DEC1_EX !keep EL, V_=extent value( length EL
bits)
IF EL<>1 THEN PRINT "AC.2nd.=";EL;V_ !!!
LET V01=V_
END IF
FOR i=A_ TO Se_
IF D2(U0+U(i),V0+V(i),P)<>0 THEN !zz(k)=xxx_1?/0?
LET L_=1
CALL DEC1_EX
LET V_=SGN(D2(U0+U(i),V0+V(i),P))*V_
LET D2(U0+U(i),V0+V(i),P)=D2(U0+U(i),V0+V(i),P) +V_*2^Al
ELSEIF
RL=0
THEN !zz(k)=000_V01
EXIT FOR
ELSE !zz(k)=000_0 ,zero
run
LET RL=RL-1
END IF
NEXT i
IF 0< EL THEN !ZRL(16) skip
IF V01=0 THEN LET V01=-1
LET D2(U0+U(i),V0+V(i),P)=V01*2^Al
END IF
LET A_=i
END IF
NEXT A_
END SUB
SUB DEC1_NS
DO
IF BC< BST THEN CALL DEC1_IN
LET W=IP(Hx) ! bits width BST
!----
LET W=A(NA+W,J)
IF 32768<=W THEN EXIT DO
LET
NA=W
! nest adr. W=0 table end
LET BC=BC-BST
LET Hx=MOD(Hx*SHb,SHb)
LOOP
LET
NA=0 !
DU0L LLLL VVVV VVVV
LET L_=MOD(IP(W/256),128) ! U0L LLLL
LET
V_=MOD(W,256)
! VVVV VVVV
IF 16< L_ THEN PRINT "unused code" !BREAK !unused code ! LET V_=BVAL("8000",16)
!----
LET W=MOD(L_,BST)
IF 0< W THEN
LET BC=BC-W
LET Hx=MOD(Hx*2^W,SHb)
ELSE
LET BC=BC-BST
LET Hx=MOD(Hx*SHb,SHb)
END IF
END SUB
SUB DEC1_IN
CALL RED_D
LET W=ORD(D$)
IF W=255 THEN
CALL RED_D
LET M=ORD(D$)
IF M<>0 THEN LET w=1/0 ! EXTYPE=3001, ffxx marker, abnormally break
END IF
LET Hx=Hx+W*2^(BST-8-BC)
LET BC=BC+8
END SUB
!-------
SUB DEC1_EX
LET V_=0
DO
IF L_< 1 THEN EXIT SUB
IF BC< L_ THEN CALL DEC1_IN
LET W=IP(Hx)
!----
IF BST>=L_ THEN EXIT DO
LET V_=V_*SHb+W
LET L_=L_-BST
LET BC=BC-BST
LET Hx=MOD(Hx*SHb,SHb)
LOOP
LET V_=V_*2^L_+IP(W*2^(L_-BST))
!----
LET BC=BC-L_
LET Hx=MOD(Hx*2^L_,SHb)
END SUB
!十進 BASIC による プログレッシブ JPG の展開と画像化。
!successive approximation subsequence 部分は、http://www.w3.org/Graphics/JPEG/itu-t81.pdf
!を見ても、説明が解りにくく、実際の例が、必要です。あくまで、個人的理解の範囲ですが、
!
!具体的、可視的なプログラムで、実行し画像化しますので、詳細事項の追跡と御参考に。
!再生できるファイルは、1000x1000 までの JPG だけで、
! baseline , spectral selection , successive approximation の3種類( web 上の、ほぼ全種)
!
!1)successive approximation AC.subsequence(Y,Cb,Cr 別々、1bit づつの処理)
!
! 0 1 1 0 0 0 0 0 0
?
! 0 0 0 0 0 1 0 0 0
?
! 0 1 0 0 0 0 0 1 0
?
! 0 1 1 0 0 1 0 1 0
?
! 0 1 1 0 0 1 0 1 0
?
! --------------------------------------------------------------------------
! ±1 b1
b2
0 0 b3
0 b4
±1 ?
!
前の終
り
RRRR
RRRR RRRR extend.
次の始め
!
! huffman.
! RRRRssss extend. b1 b2 b3 b4 …
! 3 1 (0 or 1) bit_stream=?何個になるかは、上図で、上位桁 =0 の係数が
! -1
+1 (0 or 1) RRRR 個 になるまでに通過した上位桁
<>0 の個数。
!
0 ±1
!
0 → 無変化。
!
1 → ±符号は上位桁に合せて加算。(絶対値が+1)
!
!2)successive approximation DC.subsequence(Y,Cb,Cr 別々、1bit づつの処理)
!
! ハフマン・コード RRRRssss 部は、存在せず、
! 頭からの bit_stream.で、1bit づつ、全てのblock の DC係数 に加える。
!
! AC と同様、0 → 無変化。1 → ±符号は上位桁に合せて加算。(絶対値が+1)
!
!※上記、successive approximation AC, DC とも、加える1は、
! 2^Al 倍の point transfer. としてから、加えます。
!
DEBUG ON
!------------------------
!JPG.decoder
! Baseline
! Progressive( spectral selection )( successive approximation )
!------------------------
OPTION ARITHMETIC NATIVE
OPTION BASE 0
OPTION CHARACTER byte
SET TEXT background "OPAQUE"
ASK BITMAP SIZE bmx,bmy
SET WINDOW 0,bmx, bmy,0
SET ECHO "OFF"
SET COLOR MODE "NATIVE"
!
DIM D8(1000,1000) !GDISP DSPYbr
DIM D2(1000,1000,2) !Y=D2(,,0) Cb=D2(,,1) Cr=D2(,,2)
DIM D1(1000,1000,2) !Y=D2(,,0) Cb=D2(,,1) Cr=D2(,,2)
DIM MH(2),MV(2) !R_BIN31 SOF0 MCU.Ybr.H()V()
DIM HDC(2),HAC(2) !R_BIN31 hT.table selection
DIM QS(2),CoID(255) !R_BIN31 qT.table selection
DIM M3(2)
!
DIM U(63),V(63) !zigzag
DIM DQ(7,7,3) !blk8x8 DQT
DIM DH(16,7),DV(255,7) !DHT
DIM B(255+1,7),L(255,7) !encorder & decorder's pre_table, length, ( MAKE_H2,MAKE_H0)
DIM A(2000,7) !decorder
DIM
B2(2)
!Ybr D.C.成分 starting & back_level for difference
DIM T(7,7),X(7),XO(7) !DDCT8X8, IDDCT8X8
!
LET BST=2 !huffman decorder's bit step 1=8.5s 2=6.5s 4=8.0s 8=50.0s
LET SHb=2^BST !huffman decorder *SHb(shl BST) /SHb(shr BST)
!LET YDC0=1024 !prediction 128( 50%) * {SQR(2/8)^2 * SQR(1/2)^2 * (8*8)}
!
!---zigzag table
FOR V_=0 TO 7
FOR U_=0 TO 7
READ i
LET U(i)=U_
LET V(i)=V_
NEXT U_
NEXT V_
DATA 0, 1, 5, 6,14,15,27,28
DATA 2, 4, 7,13,16,26,29,42
DATA 3, 8,12,17,25,30,41,43
DATA 9,11,18,24,31,40,44,53
DATA 10,19,23,32,39,45,52,54
DATA 20,22,33,38,46,51,55,60
DATA 21,34,37,47,50,56,59,61
DATA 35,36,48,49,57,58,62,63
!
DO
FILE GETNAME FL$, "jpg"
IF FL$="" THEN
PRINT "入力ファイル名が、ありません。"
STOP
END IF
PRINT "入力ファイル:"& FL$
!---
CLEAR
CALL IZZRL0 ! D2()<-- decord JPG
PRINT "次のファイル[ Any key ]"
beep
CHARACTER INPUT CLEAR: w$
LOOP UNTIL w$=CHR$(27) !ESC
!-------- IZZRL0 call here for display D2()
SUB MAIN65
PRINT "画像の準備中、";
CALL IDDCT8X8 ! D1()<-- iDCT<-- iDQT<-- D2()
!---
IF 1< MH(0) OR 1< MV(0) THEN ! Cb_Cr expand Blocks -->MCU scales
FOR V09=0 TO DV_-1 STEP 8*MV(0)
FOR U09=0 TO DU-1 STEP 8*MH(0)
!---MCU part.Cb.Cr
FOR V0=8*MV(0)-1 TO 0 STEP -1
FOR U0=8*MH(0)-1 TO 0 STEP -1
LET
D1(U09+U0,V09+V0,1)=D1(U09+IP(U0/MH(0)),V09+IP(V0/MV(0)),1)
LET
D1(U09+U0,V09+V0,2)=D1(U09+IP(U0/MH(0)),V09+IP(V0/MV(0)),2)
NEXT U0
NEXT V0
!---
NEXT U09
NEXT V09
END IF
! END SUB
!------ JPG 色空間 ----------------------------
! | Y | | 0.2990 +0.5870 +0.1140 | | R |
! |B-Y| = |-0.1687 -0.3313 +0.5000 | | G |
! |R-Y| | 0.5000 -0.4187 -0.0813 | | B |
!
! | R | |
1
0 +1.40200 | | Y |
! | G | = | 1 -0.34414 -0.71414 | |B-Y|
! | B | |
1 +1.77200
0 | |R-Y|
!----------------------------------------------
! SUB DSPYbr
FOR V0=0 TO DY-1
FOR U0=0 TO DX-1
LET
w1=IP(D1(U0,V0,0) +1.40200*D1(U0,V0,2))
!R
LET w2=IP(D1(U0,V0,0) -0.34414*D1(U0,V0,1) -0.71414*D1(U0,V0,2)) !G
LET w3=IP(D1(U0,V0,0)
+1.77200*D1(U0,V0,1)) !B
IF w1< 0 THEN
LET w1=0
ELSEIF 255< w1 THEN
LET w1=255
END IF
IF w2< 0 THEN
LET w2=0
ELSEIF 255< w2 THEN
LET w2=255
END IF
IF w3< 0 THEN
LET w3=0
ELSEIF 255< w3 THEN
LET w3=255
END IF
LET D8(U0,V0)=w3*65536+w2*256+w1 !(逆)BGR
NEXT U0
NEXT V0
LET w=TRUNCATE(MIN( (bmx-1)/DX,(bmy-1)/DY),1)
IF 1< w THEN LET w=IP(w)
IF 4< w THEN LET w=4
PRINT "描画の倍率=";w
MAT PLOT CELLS,IN 1,1; DX*w, DY*w :D8
END SUB
!========================
!inverse haffman Transform.
SUB IZZRL0
LET byt=0 !!!
CALL ROPEN ! FL$
!---
CALL R_BIN31(0) !A() B(i,J)L(i,J)<-- DH(), return at img.top
PRINT right$("000"& BSTR$(byt,16),4) !!!
PRINT "(";STR$(DX);"x";STR$(DY);
!---
MAT D8=ZER(DX-1,DY-1) !DSPYbr
LET i=8*MH(0) !MCU Y.Hsize
LET j=8*MV(0) !MCU Y.Vsize
LET DUM=CEIL(DX/i)*i !Uwidth=bound by MCU Y.Hsize
LET DVM=CEIL(DY/j)*j !Vwidth=bound by MCU Y.Vsize
MAT D1=ZER(DUM-1,DVM-1,2) !Y=D1(,,0) Cb=D1(,,1) Cr=D1(,,2)
MAT D2=ZER(DUM-1,DVM-1,2) !Y=D2(,,0) Cb=D2(,,1) Cr=D2(,,2)
LET MH_=MH(0)
LET MV_=MV(0)
LET DU
=DUM
!Uwidth=bound by MCU Y.Hsize
LET
DV_=DVM
!Vwidth=bound by MCU Y.Vsize
LET DU8=CEIL(DX/8)*8 !Uwidth=bound by block Y.Hsize
LET DV8=CEIL(DY/8)*8 !Vwidth=bound by block Y.Vsize
!---
PRINT "/ ";STR$(DU8);",";STR$(DV8);"/ ";STR$(DUM);",";STR$(DVM);")"
CALL frame
!---
CALL MAIN65
!---
IF 0< M THEN PRINT " (";STR$(DX);"x";STR$(DY);"/";STR$(U0);",";STR$(V0);") ";debug$;" abort by ";BSTR$(M,16) !!!
PRINT right$("000"& BSTR$(byt-2*SGN(M),16),4) !!!
CALL R_BIN31(M) ! return at img.top, or EOI
!---
DO WHILE M=BVAL("DA",16) !SOS
IF 0<=HAC(0) THEN
LET MV(0)=1
LET MH(0)=1
LET DU=DU8
LET DV_=DV8
END IF
CALL frame
LET MV(0)=MV_
LET MH(0)=MH_
LET DU=DUM
LET DV_=DVM
!---
IF Ss_<>Se_ AND M3(0)=M3(1) AND M3(1)=M3(2) THEN CALL MAIN65
!---
IF 0< M THEN PRINT "
(";STR$(DX);"x";STR$(DY);"/";STR$(U0);",";STR$(V0);") ";debug$;" abort
by ";BSTR$(M,16) !!!
PRINT right$("000"& BSTR$(byt-2*SGN(M),16),4) !!!
CALL R_BIN31(M) ! return at img.top
LOOP
CLOSE #1 ! FL$
END SUB
SUB reset0
LET B2(0)=0 !ROUND( YDC0/DQ(0,0,QS(0)) ) !prediction YDC.( 1st.reference level)
LET B2(1)=0 !prediction CbDC.
LET B2(2)=0 !prediction CrDC.
LET Hx=0 !bits stream input buffer 0~(7+8)bits, use fraction
LET BC=0 !stored bits in Hx
LET NA=0 !nest adr. in A()
LET EOB=0 !counter( end_of_band)
LET M=0
LET ext=0
END SUB
!Rolling Cube 1 の解法
!●問題
!3×3の盤に、8個のさいころが2の目が上(他の目も同じ向き)で配置されています。
!空いているマスに転がして、すべての目が1になるようにしてください。
LET t0=TIME
PUBLIC NUMERIC xSIZE,ySIZE !盤の大きさ
LET xSIZE=3
LET ySIZE=3
PUBLIC NUMERIC M(10,10) !さいころの配置 ※数字は番号、0は空き
MAT M=ZER(ySIZE+2,xSIZE+2)
DATA -1,-1,-1,-1,-1 !-1:壁 ※番兵
DATA -1, 1, 2, 3,-1 !←←←←← ※
DATA -1, 4, 0, 5,-1
DATA -1, 6, 7, 8,-1
DATA -1,-1,-1,-1,-1
MAT READ M
FOR SY=2 TO ySIZE+1 !空白の位置 ※番兵を考慮
LET SX=2
DO UNTIL SX=xSIZE+1
IF M(SY,SX)=0 THEN EXIT FOR
LET SX=SX+1
LOOP
NEXT SY
PUBLIC NUMERIC LIM !手数の上限 →最少手数
LET LIM=36 !←←←←← ※
PUBLIC NUMERIC LVL(50) !手の記録
MAT LVL=ZER
LET L=0 !0手目
CALL backtrack(L,-1,SY,SX) !※番兵を考慮
PRINT "計算時間=";TIME-t0;"秒"
END
EXTERNAL SUB backtrack(L,D,SY,SX) !1手ずつ打っていき、行き詰まれば元に戻ってやり直す
DECLARE EXTERNAL SUB Dice.rolling !外部手続き、変数の定義
DECLARE EXTERNAL NUMERIC Dice.T1(),Dice.T2(),Dice.T3(),Dice.T4()
DECLARE EXTERNAL NUMERIC Dice.T5(),Dice.T6(),Dice.T7(),Dice.T8()
DECLARE EXTERNAL NUMERIC Dice.DX(),Dice.DY()
DIM TT(6) !1つ前の保存
SUB ROTATEandMOVE(d) !さいころを回転移動する
SELECT CASE id !回転
CASE 1
MAT TT=T1
CALL rolling(d,T1)
CASE 2
MAT TT=T2
CALL rolling(d,T2)
CASE 3
MAT TT=T3
CALL rolling(d,T3)
CASE 4
MAT TT=T4
CALL rolling(d,T4)
CASE 5
MAT TT=T5
CALL rolling(d,T5)
CASE 6
MAT TT=T6
CALL rolling(d,T6)
CASE 7
MAT TT=T7
CALL rolling(d,T7)
CASE 8
MAT TT=T8
CALL rolling(d,T8)
CASE ELSE
END SELECT
LET M(SY,SX)=id !移動
LET M(TY,TX)=0
END SUB
SUB RESTORE !元に戻す
SELECT CASE id !回転
CASE 1
MAT T1=TT
CASE 2
MAT T2=TT
CASE 3
MAT T3=TT
CASE 4
MAT T4=TT
CASE 5
MAT T5=TT
CASE 6
MAT T6=TT
CASE 7
MAT T7=TT
CASE 8
MAT T8=TT
CASE ELSE
END SELECT
LET M(TY,TX)=id !移動
LET M(SY,SX)=0
END SUB
LET C=0 !枝刈り ※「残りの手数」と「目の数が一致しないさいころの数」との関係より
IF T1(3)<>1 THEN !1:目の数 ←←←←← ※
IF T1(5)=1 THEN LET C=C+2 ELSE LET C=C+1
END IF
IF T2(3)<>1 THEN
IF T2(5)=1 THEN LET C=C+2 ELSE LET C=C+1
END IF
IF T3(3)<>1 THEN
IF T3(5)=1 THEN LET C=C+2 ELSE LET C=C+1
END IF
IF T4(3)<>1 THEN
IF T4(5)=1 THEN LET C=C+2 ELSE LET C=C+1
END IF
IF T5(3)<>1 THEN
IF T5(5)=1 THEN LET C=C+2 ELSE LET C=C+1
END IF
IF T6(3)<>1 THEN
IF T6(5)=1 THEN LET C=C+2 ELSE LET C=C+1
END IF
IF T7(3)<>1 THEN
IF T7(5)=1 THEN LET C=C+2 ELSE LET C=C+1
END IF
IF T8(3)<>1 THEN
IF T8(5)=1 THEN LET C=C+2 ELSE LET C=C+1
END IF
!C個のさいころを一致させる必要があるが、残りの手数が足りないので、不可能!!!
IF L+C>LIM THEN EXIT SUB
IF C=0 AND M(3,3)=0 THEN !完成? ※「空き」が中央
!!!IF C=0 THEN !完成? ※「空き」が中央以外も含む
PRINT L;"手"
FOR i=1 TO L !上限までの手順
LET w$="LDRU" !※さいころにとっては逆となる
LET t=LVL(i)+1
PRINT w$(t:t);
NEXT i
PRINT
MAT PRINT M; !盤の状態
!! LET LIM=L !上限を狭める ←←←←← ※
END IF
IF L>=LIM THEN EXIT SUB !上限まで
!!!IF L>=2 THEN !※「空き」を左下に位置付ける(3手以降) ←←←←← 1つ下のIF文に置き換える
IF D>=0 THEN !2手以降
FOR i=D-1 TO D+1 !逆行(後ろ)を避けて、(右・前・左へ)前進する
LET DD=MOD(i,4) !連番で方向を得る
LET TX=SX+DX(DD+1) !「空き」の進路位置
LET TY=SY+DY(DD+1)
LET id=M(TY,TX) !壁、さいころの番号を得る
IF id>0 THEN !盤内なら
CALL ROTATEandMOVE(DD) !さいころを転がす
LET LVL(L+1)=DD !手を記録する
CALL backtrack(L+1,DD,TY,TX) !次へ
CALL RESTORE !元に戻す
END IF
NEXT i
ELSE
FOR i=3 TO 0 STEP -1 !※「空き」を左下に位置付ける ←←←←← 1つ下のFOR文に置き換える(そのままでも可)
!!!FOR i=0 TO 3 !全方向 ※連番
LET TX=SX+DX(i+1) !「空き」の進路位置
LET TY=SY+DY(i+1)
LET id=M(TY,TX) !壁、さいころの番号を得る
IF id>0 THEN !盤内なら
CALL ROTATEandMOVE(i) !さいころを転がす
LET LVL(L+1)=i !手を記録する
CALL backtrack(L+1,i,TY,TX) !次へ
CALL RESTORE !元に戻す
!!!EXIT FOR !※「空き」を左下に位置付ける ←←←←← 削除する
END IF
NEXT i
END IF
END SUB
MODULE Dice !さいころを転がす
!置換(Permutation)の計算
SHARE NUMERIC U(6),D(6),L(6),R(6) !置換
! 1,2,3,4,5,6
DATA 3,2,6,4,1,5 !上 ※正面を上面にする(図での水平軸)回転
DATA 1,3,4,5,2,6 !左
MAT READ U
CALL PermInverse(U,D)
MAT READ L
CALL PermInverse(L,R)
SHARE NUMERIC UU(6,6),DD(6,6),LL(6,6),RR(6,6) !置換行列
CALL PermToMatrix(U,UU)
CALL PermToMatrix(D,DD)
CALL PermToMatrix(L,LL)
CALL PermToMatrix(R,RR)
EXTERNAL SUB PermInverse(A(), iA()) !逆置換 ※iAはA以外の配列を指定すること
FOR i=1 TO UBOUND(A)
LET iA(A(i))=i
NEXT i
END SUB
!EXTERNAL SUB PermMultiply(A(),B(), AB()) !積AB ※ABはA以外かつB以外の配列を指定すること
! FOR i=1 TO UBOUND(A)
! LET AB(i)=A(B(i)) !※合成写像(AB)(i)=A(B(i))
! NEXT i
!END SUB
EXTERNAL SUB PermToMatrix(A(), M(,)) !置換の行列を得る
MAT M=ZER
FOR i=1 TO UBOUND(A)
LET M(i,A(i))=1
NEXT i
END SUB
!---------- ↑↑↑↑↑ ----------
!展開図の配置と面番号(配列の添え字)との関係
! □ 後 1
!□□□□ 左上右下 2345
! □ 正 6
PUBLIC NUMERIC T1(6),T2(6),T3(6),T4(6),T5(6),T6(6),T7(6),T8(6) !8個のさいころ
DATA 1 !目の配置 ※展開図参照
DATA 4,2,3,5
DATA 6
MAT READ T1
MAT T2=T1 !同じ向き
MAT T3=T1
MAT T4=T1
MAT T5=T1
MAT T6=T1
MAT T7=T1
MAT T8=T1
PUBLIC SUB rolling
EXTERNAL SUB rolling(i,T()) !さいころを回転させる
!DIM TT(6) !作業用
SELECT CASE i !※DX(),DY()参照
CASE 0
!CALL PermMultiply(T,L,TT) !※さいころにとっては逆となる
MAT T=T*LL !※さいころにとっては逆となる
CASE 1
!CALL PermMultiply(T,D,TT)
MAT T=T*DD
CASE 2
!CALL PermMultiply(T,R,TT)
MAT T=T*RR
CASE 3
!CALL PermMultiply(T,U,TT)
MAT T=T*UU
CASE ELSE
END SELECT
!MAT T=TT
END SUB
!---------- ↑↑↑↑↑ ----------
PUBLIC NUMERIC DX(4),DY(4) !4近傍 ※反時計まわりの連番 右:0、上:1、左:2、下:3
DATA 1, 0,-1,0
DATA 0,-1, 0,1
MAT READ DX
MAT READ DY
END MODULE
LET n=1987829
LET p=3^(n-1)
LET t=p-INT(p/n)*n
PRINT -1 !trace
PRINT t !←←←←← ここで実行時内部エラーが発生する
LET t=MOD(p,n)
PRINT -2 !trace
PRINT t
END
実行結果
-1
LET n=1987829
LET p=3^(n-1)
LET t=MOD(p,n)
PRINT -1 !trace
PRINT t !←←←←← 表示される数値が正しくない
LET t=p-INT(p/n)*n
PRINT -2 !trace
PRINT t !←←←←← ここで実行時内部エラーが発生する
END
実行結果
-1
836640
-2
!Rolling Cube 1 の解法
!●問題
!3×3の盤に、8個のさいころが1の目が上(他の目も同じ向き)で配置されています。
!空いているマスに転がして、すべての目が6になるようにしてください。
LET t0=TIME
PUBLIC NUMERIC xSIZE,ySIZE !盤の大きさ
LET xSIZE=3
LET ySIZE=3
!●さいころの盤上の配置を変更する場合
PUBLIC NUMERIC M(10,10) !さいころの配置 ※数字は番号、0は空き
MAT M=ZER(ySIZE+2,xSIZE+2)
DATA -1,-1,-1,-1,-1 !-1:壁 ※番兵
DATA -1, 1, 2, 3,-1 !←←←←← ※
DATA -1, 4, 0, 5,-1
DATA -1, 6, 7, 8,-1
DATA -1,-1,-1,-1,-1
MAT READ M
LET SY=3 !空白の位置 ※番兵を考慮
LET SX=3
!●手数の上限を変更する場合
PUBLIC NUMERIC LIM !手数の上限 →最少手数
LET LIM=49 !←←←←← ※
PUBLIC NUMERIC LVL(50) !手の記録
MAT LVL=ZER
LET L=0 !0手目
CALL backtrack(L,-1,SY,SX) !※番兵を考慮
PRINT "計算時間=";TIME-t0;"秒"
END
EXTERNAL SUB backtrack(L,D,SY,SX) !1手ずつ打っていき、行き詰まれば元に戻ってやり直す
DECLARE EXTERNAL SUB Dice.rolling !外部手続き、変数の定義
DECLARE EXTERNAL NUMERIC Dice.T1(),Dice.T2(),Dice.T3(),Dice.T4()
DECLARE EXTERNAL NUMERIC Dice.T5(),Dice.T6(),Dice.T7(),Dice.T8()
DECLARE EXTERNAL NUMERIC Dice.DX(),Dice.DY()
DIM TT(6)
SUB ROTATEandMOVE(d) !さいころを回転移動する
SELECT CASE id !回転
CASE 1
MAT TT=T1
CALL rolling(d,T1)
CASE 2
MAT TT=T2
CALL rolling(d,T2)
CASE 3
MAT TT=T3
CALL rolling(d,T3)
CASE 4
MAT TT=T4
CALL rolling(d,T4)
CASE 5
MAT TT=T5
CALL rolling(d,T5)
CASE 6
MAT TT=T6
CALL rolling(d,T6)
CASE 7
MAT TT=T7
CALL rolling(d,T7)
CASE 8
MAT TT=T8
CALL rolling(d,T8)
CASE ELSE
END SELECT
LET M(SY,SX)=id !移動
LET M(TY,TX)=0
END SUB
SUB RESTORE !元に戻す
SELECT CASE id !回転
CASE 1
MAT T1=TT
CASE 2
MAT T2=TT
CASE 3
MAT T3=TT
CASE 4
MAT T4=TT
CASE 5
MAT T5=TT
CASE 6
MAT T6=TT
CASE 7
MAT T7=TT
CASE 8
MAT T8=TT
CASE ELSE
END SELECT
LET M(TY,TX)=id !移動
LET M(SY,SX)=0
END SUB
LET C=0 !枝刈り ※「残りの手数」と「不一致なさいころの数」との関係より
IF T1(3)<>1 THEN LET C=C+1 !1:目の数 ←←←←← ※
IF T2(3)<>1 THEN LET C=C+1
IF T3(3)<>1 THEN LET C=C+1
IF T4(3)<>1 THEN LET C=C+1
IF T5(3)<>1 THEN LET C=C+1
IF T6(3)<>1 THEN LET C=C+1
IF T7(3)<>1 THEN LET C=C+1
IF T8(3)<>1 THEN LET C=C+1
IF L+C>LIM THEN EXIT SUB !不可能!!!
IF C=0 AND M(3,3)=0 THEN !完成? ※「空き」が中央
!!!IF C=0 THEN !完成? ※「空き」が中央以外も含む
PRINT L;"手"
FOR i=1 TO L !上限までの手順
SELECT CASE LVL(i)
CASE 0
PRINT "L"; !※さいころにとっては逆となる
CASE 1
PRINT "D";
CASE 2
PRINT "R";
CASE 3
PRINT "U";
CASE ELSE
END SELECT
NEXT i
PRINT
MAT PRINT M; !盤の状態
LET LIM=L !上限を狭める
END IF
IF L>=LIM THEN EXIT SUB !上限まで
!!!IF L>=2 THEN !※「空き」を左下に位置付ける(3手以降) ←←←←← 1つ下のIF文に置き換える
IF D>=0 THEN !2手以降
FOR i=D-1 TO D+1 !逆行(後ろ)を避けて、(右・前・左へ)前進する
LET DD=MOD(i,4) !連番で方向を得る
LET TX=SX+DX(DD+1) !「空き」の進路位置
LET TY=SY+DY(DD+1)
LET id=M(TY,TX) !壁、さいころの番号を得る
IF id>0 THEN !盤内なら
CALL ROTATEandMOVE(DD) !さいころを転がす
LET LVL(L+1)=DD !手を記録する
CALL backtrack(L+1,DD,TY,TX) !次へ
CALL RESTORE !元に戻す
END IF
NEXT i
ELSE
FOR i=3 TO 0 STEP -1 !※「空き」を左下に位置付ける ←←←←← 1つ下のFOR文に置き換える(そのままでも可)
!!!FOR i=0 TO 3 !全方向 ※連番
LET TX=SX+DX(i+1) !「空き」の進路位置
LET TY=SY+DY(i+1)
LET id=M(TY,TX) !壁、さいころの番号を得る
IF id>0 THEN !盤内なら
CALL ROTATEandMOVE(i) !さいころを転がす
LET LVL(L+1)=i !手を記録する
CALL backtrack(L+1,i,TY,TX) !次へ
CALL RESTORE !元に戻す
!!!EXIT FOR !※「空き」を左下に位置付ける ←←←←← 削除する
END IF
NEXT i
END IF
END SUB
MODULE Dice !さいころを転がす
!置換(Permutation)の計算
SHARE NUMERIC U(6),D(6),L(6),R(6) !置換
! 1,2,3,4,5,6
DATA 3,2,6,4,1,5 !上 ※正面を上面にする(図での水平軸)回転
DATA 1,3,4,5,2,6 !左
MAT READ U
CALL PermInverse(U,D)
MAT READ L
CALL PermInverse(L,R)
EXTERNAL SUB PermInverse(A(), iA()) !逆置換 ※iAはA以外の配列を指定すること
FOR i=1 TO UBOUND(A)
LET iA(A(i))=i
NEXT i
END SUB
EXTERNAL SUB PermMultiply(A(),B(), AB()) !積AB ※ABはA以外かつB以外の配列を指定すること
FOR i=1 TO UBOUND(A)
LET AB(i)=A(B(i)) !※合成写像(AB)(i)=A(B(i))
NEXT i
END SUB
!---------- ↑↑↑↑↑ ----------
!●さいころの目の配置(向き)を変更する場合
!展開図の配置と面番号(配列変数T1〜T8の添え字に対応)との関係
! □ 後 1
!□□□□ 左上右下 2345
! □ 正 6
PUBLIC NUMERIC T1(6),T2(6),T3(6),T4(6),T5(6),T6(6),T7(6),T8(6) !8個のさいころ
DATA 5 !目の配置 ※展開図参照
DATA 4,1,3,6
DATA 2
MAT READ T1
DATA 5
DATA 4,6,3,1
DATA 2
MAT READ T2
DATA 5
DATA 4,1,3,6
DATA 2
MAT READ T3
DATA 5
DATA 4,6,3,1
DATA 2
MAT READ T4
DATA 5
DATA 4,6,3,1
DATA 2
MAT READ T5
DATA 5
DATA 4,1,3,6
DATA 2
MAT READ T6
DATA 5
DATA 4,6,3,1
DATA 2
MAT READ T7
DATA 5
DATA 4,1,3,6
DATA 2
MAT READ T8
PUBLIC SUB rolling
EXTERNAL SUB rolling(i,T()) !さいころを回転させる
DIM TT(6) !作業用
SELECT CASE i !※DX(),DY()参照
CASE 0
CALL PermMultiply(T,L,TT) !※さいころにとっては逆となる
CASE 1
CALL PermMultiply(T,D,TT)
CASE 2
CALL PermMultiply(T,R,TT)
CASE 3
CALL PermMultiply(T,U,TT)
CASE ELSE
END SELECT
MAT T=TT
END SUB
!---------- ↑↑↑↑↑ ----------
PUBLIC NUMERIC DX(4),DY(4) !4近傍 ※反時計まわりの連番 右:0、上:1、左:2、下:3
DATA 1, 0,-1,0
DATA 0,-1, 0,1
MAT READ DX
MAT READ DY
END MODULE
!有効数字(有効桁数)の計算方法
!参考サイト http://ja.wikipedia.org/wiki/%E6%9C%89%E5%8A%B9%E6%95%B0%E5%AD%97
!参考サイト http://hp.vector.co.jp/authors/VA008683/QA_JISROUND.htm
FUNCTION ROUND10(x,n) !最近接偶数への丸めの方法で、xを小数点以下n桁に丸める
LET x=x*10^n
IF MOD(x,1)<0.5 THEN
LET x=INT(x)
ELSEIF MOD(x,1)>0.5 THEN
LET x=CEIL(x)
ELSEIF MOD(INT(x),2)=0 THEN
LET x=INT(x)
ELSE
LET x=CEIL(x)
END IF
LET ROUND10=x/10^n
END FUNCTION
!小数点以下桁数固定 FIX(数値,桁数)
DEF FIX(x,n)=ROUND10(x,n)
!DEF FIX(x,n)=ROUND(x,n) !=INT(x*10^n+0.5)/10^n
!DEF FIX(x,n)=TRUNCATE(x,n) !=IP(x*10^n)/10^n
FUNCTION SCI(x,n) !有効桁数指定 SCI(数値,桁数)
LET m=0
IF x>1 THEN !##.#なら
DO UNTIL ABS(x)<1 !0.###形式へ
LET x=x/10
LET m=m+1
LOOP
LET SCI=FIX(x,n)*10^m !※JIS Z8401『数値の丸め方』、単純な四捨五入、切捨てなど
ELSE !0.00###なら
DO UNTIL ABS(x)>=1 !#.##形式へ
LET x=x*10
LET m=m+1
LOOP
LET SCI=FIX(x,n-1)/10^m
END IF
!PRINT "x=";x; "m=";m !debug
END FUNCTION
!例 12.3+50*0.650
PRINT FIX(12.3 + SCI(50*0.650,2), 0) !2=50の有効桁数、0=50の有効桁位置
PRINT 12.3+50*0.650 !べた
PRINT
!例 ( 2.234 * 5.67815 + 100.9049 ) * 4.60
PRINT SCI(FIX( SCI(2.234*5.67815,4) + 100.9049, 2) * 4.60, 3) !毎回丸めると精度が落ちる場合がある
PRINT SCI(FIX( SCI(2.234*5.67815,5) + 100.9049, 3) * 4.60, 3) !そこで有効数字+1桁で計算を進める
PRINT ( 2.234 * 5.67815 + 100.9049 ) * 4.60
PRINT
!例 8桁関数電卓のシミュレーション ※HPはJIS丸め、シャープとカシオは四捨五入
PRINT SCI(2+5E-8,8) !JIS Z8401『数値の丸め方』 2.0000000
PRINT SCI(2+5.1E-8,8) !2.0000001
PRINT SCI(5.0000002*5.0000003,8) !25.000003
PRINT 5.0000002*5.0000003
PRINT SCI(5.0000001*5,8) !25.000000 ※2進モードではNG
PRINT 5.0000001*5
END
SET LINE COLOR "black"
FOR tt=0 TO 4100 STEP 5 !カウンタ変数は整数型とする ←←←←
LET t=tt/100 !実際の値に換算する ←←←←
LET x=r*COS(w*t)
LET y=r*SIN(w*t)
LET z=vz*t
CALL henkan(x,y,z,xrad,yrad,zrad,x3,y3,z3)
PLOT LINES:x3_,y3_;x3,y3
LET x3_=x3
LET y3_=y3
LET cnt=MOD(tt,40) !←←←←
IF cnt=0 THEN
LET x=0
LET y=0
CALL henkan(x,y,z,xrad,yrad,zrad,x0_,y0_,z0_)
PLOT LINES:x0_,y0_;x3_,y3_
PLOT POINTS:x3_,y3_
END IF
NEXT tt !←←←←
OPTION ARITHMETIC NATIVE
OPTION BASE 0
DIM D8(500,500)
!
SET VIEWPORT 0, 0.4, 0.6, 1
CALL sample(DX$,DY$)
LET DX=VAL(DX$)
LET DY=VAL(DY$)
MAT D8=ZER(DX,DY)
!
SET VIEWPORT 0, 1, 0, 1
SET WINDOW 0, 500, 500, 0
!
! SET COLOR MODE "NATIVE" ! ←これを入れると正常にコピーされる。
!
ASK PIXEL ARRAY (0,0) D8
MAT PLOT CELLS,IN 250,250; 450,450: D8
!
!main00
! (
! )
END
EXTERNAL SUB sample(DX$,DY$)
! マンデルブロー(Complex\mandelbm.bas の着色改変)
OPTION ARITHMETIC COMPLEX
SET COLOR MODE "REGULAR"
SET POINT STYLE 1
FOR n=0 TO 50
SET COLOR MIX( n) 0
,0 ,n/51 !BLACK =< < BLUE
SET COLOR MIX( 51+n) 0 ,n/51 ,1 !BLUE =< < CYAN
SET COLOR MIX(102+n) 0 ,1 ,1-n/51 !CYAN =< < GREEN
SET COLOR MIX(153+n) n/51,1 ,0 !GREEN =< < YELLOW
SET COLOR MIX(204+n) 1 ,1-n/51,0 !YELLOW =< < RED
NEXT n
LET XL=-2
LET XR=.8
LET w1=XR-XL
LET w2=w1/2
SET WINDOW XL, XR,-w2,w2
ASK PIXEL SIZE(XL,-w2; XR,w2) px,py
!
FOR x=XL TO XR STEP w1/(px-1)
FOR y=-w2-.49*w1/(py-1) TO w2 STEP w1/(py-1) !故意に(x,0)を描点の間に挟む。
LET z=0
FOR n=1 TO 255
LET z=z^2+COMPLEX(x,y)
IF 2< ABS(z) THEN
IF
n< 64 THEN SET POINT COLOR n*4 ELSE SET POINT COLOR 255
PLOT POINTS :x,y !上下の対象プロットをしない。
EXIT FOR
END IF
NEXT n
NEXT y
NEXT x
LET DX$=STR$(px-1)
LET DY$=STR$(py-1)
END SUB
!========================
SUB W_BIN31
!---SOI
CALL WRT_H("FFD8")
!---APP0
CALL WRT_H("FFE0")
CALL WRT_W( 2+14) !size
CALL WRT_M("JFIF"& CHR$(0))
CALL WRT_H("0101") !ver 1.1
CALL WRT_D(1) !0=none 1=dpi 2=dpcm
CALL WRT_W(72) !Xd 72 アスペクト比 IE6(no) imaging(ok)
CALL WRT_W(72) !Yd 72 アスペクト比
CALL WRT_D(0) !Xt 0
CALL WRT_D(0) !Yt 0
!---DQT.Y.C
CALL WRT_H("FFDB")
LET W=2 !start size
FOR J=0 TO CMO/2 !CMO=0(mono.) CMO=2(color)
LET W=W+1+64 !+ID +QT
NEXT J
CALL WRT_W( W) !size
FOR J=0 TO CMO/2 ! CMO=0(mono.) CMO=2(color)
CALL WRT_D(J) !J= (0)Y.DQ (1)C.DQ
FOR I=0 TO 63
CALL WRT_D( DQ(U(i),V(i),J) )
NEXT I
NEXT J
!---SOF0
CALL WRT_H("FFC0")
IF CMO=0 THEN CALL WRT_W( 11) ELSE CALL WRT_W( 17) !size
CALL WRT_D( 8) !8bit at RGB
CALL WRT_W( DY) !V.pixels
CALL WRT_W( DX) !H.pixels
IF CMO=0 THEN
CALL WRT_H("01") !1 items
CALL WRT_H("011100") !Y MCU(H:V) DQT
ELSE
CALL WRT_H("03") !3 items
CALL WRT_H("01"&
STR$(MH(0))& STR$(MV(0))& "0"& STR$(QS(0)))
!Y MCU(H:V) DQT
CALL WRT_H("02"& STR$(MH(1))& STR$(MV(1))& "0"& STR$(QS(1))) !Cb - -
CALL WRT_H("03"& STR$(MH(2))& STR$(MV(2))& "0"& STR$(QS(2))) !Cr - -
END IF
!---DHT
CALL WRT_H("FFC4")
LET W=2 !start size
FOR J=0 TO CMO+1 !CMO=0(mono.) CMO=2(color)
LET W=W+1+16+DH(0,J) !+ID +HT +VT
NEXT J
CALL WRT_W( W) !size
FOR J=0 TO
CMO+1
!CMO=0(mono.) CMO=2(color)
CALL WRT_D( 16*MOD(J,2)+IP(J/2) ) ! 00h=YDC 10h=YAC 01h=CDC 11h=CAC
FOR I=1 TO
16
!(J) 0 =YDC 1 =YAC 2 =CDC 3 =CAC
CALL WRT_D( DH(I,J))
NEXT I
FOR I=0 TO DH(0,J)-1
CALL WRT_D( DV(I,J))
NEXT I
NEXT J
!---SOS
CALL WRT_H("FFDA")
IF CMO=0 THEN
CALL WRT_W(8) !size
CALL WRT_D(1) !1 items
CALL WRT_H("0100") !No. Y.HDC/HAC
ELSE
CALL WRT_W(12) !size
CALL WRT_D( 3) !3 items
CALL WRT_H("0100") !No. Y.HDC/HAC
CALL WRT_H("0211") !No. Cb.HDC/HAC
CALL WRT_H("0311") !No. Cr.HDC/HAC
END IF
CALL WRT_H("003F00") !band 0~63, AhAl=00
END SUB
!----------------
!open write binary
SUB WOPEN
OPEN #1:NAME FL$
ERASE #1
END SUB
!sequential write byte
SUB WRT_D( D)
PRINT #1 :CHR$(D);
LET byt=byt+1 !!!
END SUB
!sequential write word
SUB WRT_W( w)
PRINT #1 :CHR$(IP(w/256));CHR$(MOD(w,256));
LET byt=byt+2 !!!
END SUB
!sequential write binary massage W$
SUB WRT_M( w$)
FOR w=1 TO LEN(w$)
PRINT #1 :MID$(w$,w,1);
NEXT w
LET byt=byt+w-1 !!!
END SUB
!sequential write binary hex.massage w$
SUB WRT_H( w$)
FOR w=1 TO LEN(w$) STEP 2
PRINT #1 :CHR$(BVAL(MID$(w$,w,2),16));
NEXT w
LET byt=byt+LEN(w$)/2 !!!
END SUB
!=====================
! print huffman_table
SUB list_HT( m$,J)
PRINT m$;" 頻度 座標 bit コード(";
IF MOD(B(256,J),2)=1 THEN PRINT "座標順)" ELSE PRINT "生成順、頻度降順)"
LET sum=0
FOR i=0 TO 255
IF L(i,J)<>0 THEN
IF MOD(B(256,J),2)=1 THEN ! 1=Sort_value. Encorder
LET V_=i
LET
w$=" "& RIGHT$(" "&
STR$(SV(i,J)),4)& " " ! times
LET sum=sum+L(i,J)*SV(i,J)
ELSE !
0=Sort_length. Decorder
LET V_=DV(i,J)
LET
w$=" "& RIGHT$(" "&
STR$(S_(i,J)),4)& " " ! times
LET sum=sum+L(i,J)*S_(i,J)
END IF
LET w$=w$& RIGHT$("0"& BSTR$(V_,16),2)& " " ! value
LET w$=w$& RIGHT$(" "& STR$(L(i,J)),2)& " " ! length
!--- huffman code
LET H_=B(i,J) ! code
LET L_=L(i,J) ! length
!--- bit_pattern
LET w$=w$& left$(right$("0000000"& BSTR$(H_,2),16),L_)
PRINT w$
END IF
NEXT i
PRINT " 合計( 頻度 * bit)=";sum
END SUB
END
EXTERNAL SUB sample(DX$,DY$)
! マンデルブロー(Complex\mandelbm.bas の着色改変)
OPTION ARITHMETIC COMPLEX
SET COLOR MODE "REGULAR"
SET POINT STYLE 1
FOR n=1 TO 51
SET COLOR MIX( n) 0
,0 ,n/51 !BLACK < < BLUE
SET COLOR MIX( 51+n) 0
,n/51 ,1 !BLUE <
< CYAN
SET COLOR MIX(102+n) 0 ,1 ,1-n/51 !CYAN < < GREEN
SET COLOR MIX(153+n) n/51,1 ,0 !GREEN < < YELLOW
SET COLOR MIX(204+n) 1 ,1-n/51,n/51 !YELLOW< < MAGENTA
NEXT n
LET XL=-2
LET XR=.8
LET w1=XR-XL
LET w2=w1/2
SET WINDOW XL, XR,-w2,w2
ASK PIXEL SIZE(XL,-w2; XR,w2) px,py
!
FOR x=XL TO XR+1e-6 STEP w1/(px-1)
FOR y=-w2-.49*w1/(py-1) TO w2 STEP w1/(py-1) !故意に(x,0)を描点の間に挟む。
LET z=0
FOR n=1 TO 255
LET z=z^2+COMPLEX(x,y)
IF 2< ABS(z) THEN
IF
n< 64 THEN SET POINT COLOR n*4 ELSE SET POINT COLOR 253
PLOT POINTS :x,y !上下の対象プロットをしない。
EXIT FOR
END IF
NEXT n
NEXT y
NEXT x
LET DX$=STR$(px)
LET DY$=STR$(py)
END SUB
!-------------------
! make huffman tree
SUB TREE3
MAT Tr=ZER
FOR i=0 TO SE
LET F_(i)=S_(i,P)
NEXT i
!---minimum2
DO
LET w=1e8
FOR i=0 TO SE
IF F_(i)< w THEN
LET w=F_(i)
LET Ad1=i ! minimum1
END IF
NEXT i
LET w=1e8
FOR i=0 TO SE
IF F_(i)< w AND i<>Ad1 THEN
LET w=F_(i)
LET Ad2=i ! minimum2
END IF
NEXT i
IF w=1e8 THEN EXIT DO
IF Ad1>Ad2 THEN swap Ad1,Ad2
!---
LET F_(Ad1)=F_(Ad1)+F_(Ad2)
LET F_(Ad2)=1e9
!---
FOR Le1=16 TO 1 STEP -1
IF Tr(Le1,Ad1,1)>0 OR Tr(Le1,Ad1,3)>0 THEN EXIT FOR
NEXT Le1
FOR Le2=16 TO 1 STEP -1
IF Tr(Le2,Ad2,1)>0 OR Tr(Le2,Ad2,3)>0 THEN EXIT FOR
NEXT Le2
LET Le0=MAX( Le1,Le2 )+1
!---
LET Tr(Le0,Ad1,0)=Le1
LET Tr(Le0,Ad1,1)=Ad1
LET Tr(Le0,Ad1,2)=Le2
LET Tr(Le0,Ad1,3)=Ad2
LOOP
!---make DH()
LET DH(0,P)=SE+1
LET k=0
CALL bitl(Le0,Ad1)
FOR Ad=0 TO SE
LET DH(Tr(0,Ad,1),P)=DH(Tr(0,Ad,1),P)+1
NEXT Ad
END SUB
SUB bitl(Le,Ad)
IF 0< Le THEN
LET k=k+1
CALL bitl( Tr(Le,Ad,0), Tr(Le,Ad,1) )
CALL bitl( Tr(Le,Ad,2), Tr(Le,Ad,3) )
LET k=k-1
ELSE
LET Tr(Le,Ad,1)=k
END IF
END SUB
!-------------------
! Quick Sort S_()
SUB Qsort(L,R) ! 降順にセット。
local i,j
LET i=L
LET j=R
LET Tx=S_(IP((L+R)/2),P)
DO
DO WHILE S_(i,P) >Tx ! 降順>、昇順<
LET i=i+1
LOOP
DO WHILE Tx >S_(j,P) ! 降順>、昇順<
LET j=j-1
LOOP
IF j< i THEN EXIT DO ! 等号付 j<=i は、暴走。
SWAP S_(i,P),S_(j,P)
SWAP DV(i,P),DV(j,P)
LET i=i+1
LET j=j-1
LOOP UNTIL j< i ! 等号付 j<=i は、低速。
IF L< j THEN CALL Qsort(L,j)
IF i< R THEN CALL Qsort(i,R)
END SUB
!===================================
! make encorder table B()L()<-- DH()
SUB MAKE_H2
MAT L=ZER
FOR J=0 TO CMO+1
LET I=0 ! コード生成 順番(短い順)
LET Hx=0
LET Tx=BVAL("8000",16)
FOR L_=1 TO 16
FOR N=1 TO DH(L_,J)
LET V_=DV(I,J) ! 座標DV(頻度降順)
LET L(V_,J)=L_
LET B(V_,J)=Hx ! コード(座標V_)
LET I=I+1
LET Hx=Hx+Tx
NEXT N
LET Tx=Tx/2
NEXT L_
LET B(256,J)=1
NEXT J
END SUB
!==============================
!Fast Discrete Cosin Transform.( M=8x8, DCT-2 )
SUB DDCT8X8
FOR P=0 TO CMO ! (0=Y,1=Cb,2=Cr)
FOR V0=0 TO DV_-1 STEP 8*MV(0)/MV(P)
FOR U0=0 TO DU-1 STEP 8*MH(0)/MH(P)
FOR Y_=0 TO 7
LET w=Y_*MV(0) !sampling pt.Y
FOR X_=0 TO 7 !level shift, sampling CbCr from MCU
IF
P=0 THEN LET X(X_)=D2(U0+X_,V0+Y_,P)-128 ELSE LET
X(X_)=D2(U0+X_*MH(0),V0+w,P)
NEXT X_
CALL WANG
FOR U_=0 TO 7
LET T(U_,Y_)=X(U_)
NEXT U_
NEXT Y_
FOR U_=0 TO 7
FOR Y_=0 TO 7
LET X(Y_)=T(U_,Y_)
NEXT Y_
CALL WANG
FOR V_=0 TO 7
LET
D2(U0+U_,V0+V_,P)=ROUND( X(V_)/DQ(U_,V_,QS(P)) ) ! Quantization
NEXT V_
NEXT U_
NEXT U0
NEXT V0
NEXT P
END SUB
!=============================
!Fast Discrete Cosin Transform
!Wang.( M=8, DCT-2 )
SUB WANG
LET XO(0)=X(0)+X(7)
LET XO(1)=X(1)+X(6)
LET XO(2)=X(2)+X(5)
LET XO(3)=X(3)+X(4)
LET XO(4)=X(3)-X(4)
LET XO(5)=X(2)-X(5)
LET XO(6)=X(1)-X(6)
LET XO(7)=X(0)-X(7)
!
LET X(0)=XO(0)+XO(3)
LET X(1)=XO(1)+XO(2)
LET X(2)=XO(1)-XO(2)
LET X(3)=XO(0)-XO(3)
LET X(4)=XO(7)*SQR(2)
LET X(5)=XO(6)-XO(5)
LET X(6)=XO(6)+XO(5)
LET X(7)=XO(4)*SQR(2)
!
LET XO(0)=(COS(PI/4)*X(0)+COS(PI/4)*X(1))
LET XO(1)=(COS(PI/4)*X(0)-COS(PI/4)*X(1)) !fin 0(0),1(4)
LET XO(2)=(COS(PI/8)*X(3)+SIN(PI/8)*X(2))
LET XO(3)=(COS(PI*3/8)*X(3)-SIN(PI*3/8)*X(2)) !fin 2(2),3(6)
LET XO(4)=X(4)
LET XO(5)=X(6)
LET XO(6)=X(5)
LET XO(7)=X(7)
!
LET X(4)=XO(4)+XO(5)
LET X(5)=XO(4)-XO(5)
LET X(6)=-XO(6)+XO(7)
LET X(7)=XO(6)+XO(7)
!
LET XO(4)=(COS(PI/16)*X(4)+SIN(PI/16)*X(7))
LET XO(5)=(COS(PI*5/16)*X(5)+SIN(PI*5/16)*X(6))
LET XO(6)=(SIN(PI*5/16)*X(5)-COS(PI*5/16)*X(6))
LET XO(7)=(SIN(PI/16)*X(4)-COS(PI/16)*X(7))
!
LET X(0)=SQR(2/8)*XO(0)
LET X(4)=SQR(2/8)*XO(1)
LET X(2)=SQR(2/8)*XO(2)
LET X(6)=SQR(2/8)*XO(3)
LET X(1)=SQR(1/8)*XO(4)
LET X(5)=SQR(1/8)*XO(5)
LET X(3)=SQR(1/8)*XO(6)
LET X(7)=SQR(1/8)*XO(7)
END SUB
! haffman Transform. main
SUB ZZRL0
! ---pass-1 analize frequency SV(nnnn,ssss) -->DV( ,J) DH( ,J)
IF 0< MHT OR DH(0,0)=0 THEN CALL ZFRE0
!---pass-2
CALL MAKE_H2 ! huffman code=B(V,J) len.=L(V,J) <-- DH( ,J) DV( ,J)
!---
LET byt=0 !!!
CALL WOPEN
CALL W_BIN31
!---
LET Hw=0 !bits stream buffer
LET BC=0 !bits in Hw
!---
LET B2(0)=0 ! Y.DC( start prediction)
LET B2(1)=0 ! Cb.DC
LET B2(2)=0 ! Cr.DC
!---
FOR V09=0 TO DV_-1 STEP 8*MV(0)
FOR U09=0 TO DU-1 STEP 8*MH(0)
!---MCU
FOR P=0 TO CMO !( 0=Y 1=Cb 2=Cr)
FOR V0=V09 TO V09+8*MV(P)-1 STEP 8
FOR U0=U09 TO U09+8*MH(P)-1 STEP 8
CALL W_BLK0
NEXT U0
NEXT V0
NEXT P
!---
NEXT U09
NEXT V09
CALL W_FLUSH
!---EOI
CALL WRT_H("FFD9")
CLOSE #1
PRINT "byte size:";byt
END SUB
!------
SUB F_BLK0
LET J=2*SGN(P) ! ( 0=Y 1=Cb 2=Cr)
!---D.C.part
LET W=D2(U0+U(0),V0+V(0),P)
LET SY=W-B2(P)
LET B2(P)=W ! previous of D.C.difference
IF SY<>0 THEN LET SS=LEN(BSTR$(ABS( SY),2)) ELSE LET SS=0 ! bit_length
LET SV(SS,J)=SV(SS,J)+1
!---A.C.parts
FOR AE=63 TO 0 STEP -1
IF 0<>D2(U0+U(AE),V0+V(AE),P) THEN EXIT FOR
NEXT AE
!---
LET Z=0 !zero run counter
FOR A_=1 TO AE
LET SY=D2(U0+U(A_),V0+V(A_),P)
IF SY=0 AND Z< 15 THEN
LET Z=Z+1
ELSE
IF SY<>0 THEN LET SS=LEN(BSTR$(ABS(SY),2)) ELSE LET SS=0 ! bit_length
LET W=Z*16+SS
LET Z=0
LET SV(W,J+1)=SV(W,J+1)+1
END IF
NEXT A_
IF A_< 64 THEN LET SV(0,J+1)=SV(0,J+1)+1 !End Of Block
END SUB
SUB W_BLK0
LET J=2*SGN(P) ! ( 0=Y 1=Cb 2=Cr)
!---D.C.part absolute SY bits length
LET W=D2(U0+U(0),V0+V(0),P)
LET SY=W-B2(P)
LET B2(P)=W ! previous of D.C.difference
IF SY<>0 THEN LET SS=LEN(BSTR$(ABS( SY),2)) ELSE LET SS=0 ! bit_length
LET L_=L(SS,J)
LET Ww=B(SS,J)
CALL W_HUFF
!---D.C.extent
IF SS<>0 THEN
IF SY< 0 THEN LET SY=SY+2^SS-1 !add maxim. in same bit_length.
LET L_=SS
LET Ww=SY*2^(16-L_)
CALL W_HUFF
END IF
!---A.C.parts
FOR AE=63 TO 0 STEP -1
IF 0<>D2(U0+U(AE),V0+V(AE),P) THEN EXIT FOR
NEXT AE
!---
LET Z=0 !zero run counter
FOR A_=1 TO AE
LET SY=D2(U0+U(A_),V0+V(A_),P)
IF SY=0 AND Z< 15 THEN
LET Z=Z+1
ELSE
IF SY<>0 THEN LET SS=LEN(BSTR$(ABS(SY),2)) ELSE LET SS=0 ! bit_length
LET W=Z*16+SS
LET Z=0
LET L_=L(W,J+1)
LET Ww=B(W,J+1)
CALL W_HUFF
!---A.C.extent
IF SS<>0 THEN
IF
SY< 0 THEN LET SY=SY+2^SS-1 !add maxim. in same bit_length.
LET L_=SS
LET Ww=SY*2^(16-L_)
CALL W_HUFF
END IF
END IF
NEXT A_
IF A_< 64 THEN
LET L_=L(0,J+1)
LET Ww=B(0,J+1)
CALL W_HUFF !End Of Block
END IF
END SUB
!-----
!Ww:b15 ~0 左詰め 入力 bit_stream. L_:bit長
SUB W_HUFF
LET Hw=Hw+Ww*2^(-BC-8)
LET BC=BC+L_
DO WHILE 8<=BC
CALL WRT_D( IP(Hw))
IF IP(Hw)=255 THEN CALL WRT_D( 0)
LET Hw=FP(Hw)*256
LET BC=BC-8
LOOP
END SUB
!flush bit buffer with byte_bound( fill"1"in blank)
SUB W_FLUSH
IF BC<>0 THEN
LET w=Hw +2^(8-BC)-1
CALL WRT_D( w)
IF w=255 THEN CALL WRT_D( 0)
END IF
END SUB
!=====================
!pre hafman Transform.
!sort frequency S_() of nnnnssss( zero_run_length data)
!make DH() DV()
SUB MAKE_DHT
MAT DH=ZER
!---debug monitor
PRINT "-----------------------------------------"
FOR J=0 TO CMO+1 ! CMO =0=mono =2=color
PRINT "Zero_Run_Length 頻度表 (→)画素bit幅0~15、(↓)直前0数0~15"
PRINT W_$(J)
CALL msg00( SV, 0,255,J, 5) ! SV( 0~255, J)
PRINT "total=";Tx
NEXT J
PRINT
!---
FOR P=0 TO CMO+1 ! P(0~1=Y.DC~AC 2~3=C.DC~AC), CMO( 0=mono 2=color)
!--- make S_(,)DV(,)<-- SV(,)
LET SE=-1
FOR i=0 TO 255
IF SV(i,P)<>0 THEN
LET SE=SE+1
LET S_(SE,P)=SV(i,P)
LET DV(SE,P)=i
END IF
NEXT i
PRINT "===================================="
PRINT W_$(P)
PRINT "Zero Run Length 頻度表を詰めたもの"
CALL msg00( S_, 0,SE,P, 5) ! S_(0~SE, P)
PRINT "表座標(0~F=直前0数:0~F=画素bit長)"
CALL msg0x( DV, 0,SE,P, 5) ! DV(0~SE, P)
!---
CALL Qsort(0,SE)
CALL TREE3
!---
PRINT
PRINT " Encoder DHT table"
PRINT " (→)コード長1~16の、各個数"
CALL msg0x( DH, 1,16 ,P, 3) ! DH(1~16, P)
PRINT " 頻度順の、表座標(0~F=直前0数:0~F=画素bit長)"
CALL msg0x( DV, 0,Tx-1,P, 3) ! DV(0~Tx-1, P)
PRINT
NEXT P
END SUB
SUB msg00( M(,), S,E,J, w)
LET Tx=0
LET w$=""
FOR i=S TO E
LET Tx=Tx+M(i,J)
LET w$=w$& USING$( REPEAT$("#",w),M(i,J))
IF MOD(i-S,16)=15 THEN LET w$=w$& crlf$
NEXT i
IF MOD(i-S,16)=0 THEN PRINT w$; ELSE PRINT w$
END SUB
SUB msg0x( M(,), S,E,J, w)
LET Tx=0
LET w$=""
FOR i=S TO E
LET Tx=Tx+M(i,J)
LET w$=w$& REPEAT$(" ",w-2)& RIGHT$("0"& BSTR$(M(i,J),16),2)
IF MOD(i-S,16)=15 THEN LET w$=w$& crlf$
NEXT i
IF MOD(i-S,16)=0 THEN PRINT w$; ELSE PRINT w$
END SUB
SUB SetWindowPos( handle,C2, x0,y0,xw,yw, nFLG) !nFLG: 0=x0y0xwyw 1=x0y0 2=xwyw
ASSIGN "user32.dll","SetWindowPos"
END SUB
!----------------------------------------------------------
LET FL$="baseline.jpg" ! 削除すると、ダイアログ・ボックス入力。
SET ECHO "OFF"
ASK DIRECTORY s$
IF FL$>"" THEN PRINT "カレント DIR:"& s$ ELSE file getname FL$, "jpg"
PRINT "出力ファイル:"& FL$
IF FL$>"" THEN PRINT "上書き。又は作成されます。…"& "Ok?[Enter]"
IF FL$>"" THEN CHARACTER INPUT k$
IF FL$="" OR k$<>CHR$(13) THEN
PRINT "中止"
STOP
END IF
OPTION ARITHMETIC NATIVE
OPTION BASE 0
OPTION CHARACTER byte
SET TEXT background "OPAQUE"
ASK BITMAP SIZE bmx,bmy
SET WINDOW 0,bmx, bmy,0
!
DIM D8(1000,1000) !sample picture
DIM D2(1000,1000,2) !Y=D2(,,0) Cb=D2(,,1) Cr=D2(,,2)
DIM MH(2),MV(2) !MCU.Ybr.H()V()
DIM HDC(2),HAC(2) !hT.table selection
DIM QS(2),CoID(255) !qT.table selection
!
DIM U(63),V(63) !zigzag
DIM DQ(7,7,3) !DQT
DIM DH(16,7),DV(255,7) !DHT
DIM B(255+1,7),L(255,7) !huffman.code & length ( MAKE_H2 )
DIM B2(2) !Ybr D.C.成分 starting
DIM T(7,7),X(7),XO(7) !DDCT8X8
!
!---encorder
DIM SV(255,3) !ZFRE0 頻度SV( 座標)
DIM
S_(255,3) !MAKE_DHT
頻度SV( 座標)--> 頻度S_( 降順No.) 座標DV( 降順No.)
DIM F_(255),Tr(16,255,3) !TREE3
!---lister
LET crlf$=CHR$(13)& CHR$(10)
DIM W_$(7)
LET W_$(0)="Y.DC"
LET W_$(1)="Y.AC"
LET W_$(2)="C.DC"
LET W_$(3)="C.AC"
!
SET VIEWPORT 0,0.4,0.6,1
CALL sample(DX$,DY$) !サンプル画像。
LET DX=VAL(DX$)
LET DY=VAL(DY$)
MAT D8=ZER(DX-1,DY-1)
SET VIEWPORT 0, 1, 0, 1
SET WINDOW 0,bmx, bmy,0
SET COLOR MODE "NATIVE"
ASK PIXEL ARRAY (0,0) D8
! MAT PLOT CELLS,IN 250,250; 450,450: D8 ! check
!
LET CMO=2 !CMO=0(mono.) CMO=2(color)
LET SD=1 !encoder 量子化テーブル調整 1/SD
CALL DQTINI !DQ(,,0)~DQ(,,1)~{zigzag U()V()},MH(),MV()
LET DU =CEIL(DX/(8*MH(0)))*8*MH(0) !Uwidth= (8X8)*2 bound by MCU size
LET DV_=CEIL(DY/(8*MV(0)))*8*MV(0) !Vwidth= (8X8)*1
MAT D2=ZER(DU-1,DV_-1,2) !Y=D2(,,0) Cb=D2(,,1) Cr=D2(,,2)
!
CALL YbrRGB ! Ybr D2()<--RGB D8()
LET MHT=1 ! flag. uncondition making huff.table
CALL DDCT8X8 ! D2() -->DCT -->Quantization
CALL ZZRL0 ! encoder
!---
PRINT "-------------------------"
PRINT "Encoder huffman Code"
FOR J=0 TO CMO+1
CALL list_HT(W_$(J),J) ! value Sort !H2.LST
NEXT J
beep
PRINT "終了"
!---------
SUB YbrRGB
!--------- JPG 色空間 -------------------------
! | Y | | 0.2990 +0.5870 +0.1140 | | R |
! |B-Y| = |-0.1687 -0.3313 +0.5000 | | G |
! |R-Y| | 0.5000 -0.4187 -0.0813 | | B |
!
! | R | | 1
0 +1.40200 | | Y |
! | G | = | 1 -0.34414 -0.71414 | |B-Y|
! | B | |
1 +1.77200
0 | |R-Y|
!----------------------------------------------
FOR V0=0 TO DY-1
FOR U0=0 TO DX-1
LET w1= MOD(D8(U0,V0),256) !R
LET w2=MOD(IP(D8(U0,V0)/256),256) !G
LET w3= IP(D8(U0,V0)/65536) !B
LET D2(U0,V0,0)= 0.2990*w1+0.5870*w2+0.1140*w3 !Y
LET D2(U0,V0,1)=-0.1687*w1-0.3313*w2+0.5000*w3 !Cb
LET D2(U0,V0,2)= 0.5000*w1-0.4187*w2-0.0813*w3 !Cr
NEXT U0
NEXT V0
END SUB
!-----------
SUB DQTINI
RESTORE
!---DQT quantization
FOR j=0 TO 1
FOR V_=0 TO 7
FOR U_=0 TO 7
READ W
LET DQ(U_,V_,j)=CEIL(W/SD) ! inhibit 0
NEXT U_
NEXT V_
NEXT j
!---zigzag-U()V()
FOR V_=0 TO 7
FOR U_=0 TO 7
READ i
LET U(i)=U_
LET V(i)=V_
NEXT U_
NEXT V_
!---HT selection
MAT READ HDC !Y Cb Cr
MAT READ HAC !Y Cb Cr
!---QT selection
MAT READ QS !Y Cb Cr
!---MCU size
MAT MH=CON !Y Cb Cr =1
MAT MV=CON !Y Cb Cr =1
IF 0< CMO THEN
LET MH(0)=2 !Y
LET MV(0)=2 !Y
END IF
END SUB
!---quantization table
!輝度( SMPTE 370M ).Y
!*DQTY
DATA 32, 16, 17, 18, 18, 19, 42, 44
DATA 16, 17, 18, 18, 19, 38, 43, 45
DATA 17, 18, 19, 19, 40, 41, 45, 48
DATA 18, 18, 19, 40, 41, 42, 46, 49
DATA 18, 19, 40, 41, 42, 43, 48,101
DATA 19, 38, 41, 42, 43, 44, 98,104
DATA 42, 43, 45, 46, 48, 98,109,116
DATA 44, 45, 48, 49,101,104,116,123
!---quantization table
!色差( SMPTE 370M ).Cb Cr
!*DQTC
DATA 32, 16, 17, 25, 26, 26, 42, 44
DATA 16, 17, 25, 25, 26, 38, 43, 91
DATA 17, 25, 26, 27, 40, 41, 91, 96
DATA 25, 25, 27, 40, 41, 84, 93,197
DATA 26, 26, 40, 41, 84, 86,191,203
DATA 26, 38, 41, 84, 86,177,197,209
DATA 42, 43, 91, 93,191,197,219,232
DATA 44, 91, 96,197,203,209,232,246
!---Zigzag table
DATA 0, 1, 5, 6,14,15,27,28
DATA 2, 4, 7,13,16,26,29,42
DATA 3, 8,12,17,25,30,41,43
DATA 9,11,18,24,31,40,44,53
DATA 10,19,23,32,39,45,52,54
DATA 20,22,33,38,46,51,55,60
DATA 21,34,37,47,50,56,59,61
DATA 35,36,48,49,57,58,62,63
!---HT selection
DATA 0,2,2 !DC. Y Cb Cr
DATA 1,3,3 !AC. Y Cb Cr
!---QT selection
DATA 0,1,1 ! Y Cb Cr
!==========================================
! analizing frequency SV(nnnn,ssss) for DHT
SUB ZFRE0
MAT SV=ZER
LET B2(0)=0 ! Y.DC( start prediction)
LET B2(1)=0 ! Cb.DC
LET B2(2)=0 ! Cr.DC
!---
FOR V09=0 TO DV_-1 STEP 8*MV(0)
FOR U09=0 TO DU-1 STEP 8*MH(0)
!---MCU
FOR P=0 TO CMO ! ( 0=Y 1=Cb 2=Cr)
FOR V0=V09 TO V09+8*MV(P)-1 STEP 8
FOR U0=U09 TO U09+8*MH(P)-1 STEP 8
CALL F_BLK0
NEXT U0
NEXT V0
NEXT P
!---
NEXT U09
NEXT V09
!---
CALL MAKE_DHT !DH( ,J) DV( ,J) <--S_( ,J)
END SUB
LET t0=TIME
LET p=1987829
PRINT modpow(3,p-1,p)
PRINT "計算時間=";TIME-t0
LET t0=TIME
LET s=1
FOR k=1 TO p-1
LET s=MOD(s*3,p)
NEXT k
PRINT s
PRINT "計算時間=";TIME-t0
END
EXTERNAL FUNCTION modpow(a,n,b) !a^n≡x mod b のxを返す ※nは非負整数
IF n<0 OR n<>INT(n) THEN !非負整数以外なら
PRINT "modpow関数でパラメータが不適当です。"
STOP
ELSE
LET S=1
DO WHILE n>0 !べき乗nを2進展開する
IF MOD(n,2)=1 THEN LET S=MOD(S*a,b) !ビットが1なら計算する
LET a=MOD(a*a,b)
LET n=INT(n/2)
LOOP
LET modpow=S
END IF
END FUNCTION
-----------------------------------------------
[追記] SET COLOR MODE "NATIVE" …がダメな場合。
SET VIEWPORT 0, 1, 0, 1
SET WINDOW 0,bmx, bmy,0
! SET COLOR MODE "NATIVE" ←取り去る
ASK PIXEL ARRAY (0,0) D8
(
)
!---------
SUB YbrRGB
(
)
↓これに、差替え。
FOR V0=0 TO DY-1
FOR U0=0 TO DX-1
ASK COLOR MIX( D8(U0,V0)) w1,w2,w3 ! R,G,B (0~1)
LET D2(U0,V0,0)= 255*( 0.2990*w1+0.5870*w2+0.1140*w3) !Y
LET D2(U0,V0,1)= 255*(-0.1687*w1-0.3313*w2+0.5000*w3) !Cb
LET D2(U0,V0,2)= 255*( 0.5000*w1-0.4187*w2-0.0813*w3) !Cr
NEXT U0
NEXT V0
!------------------------
EXTERNAL SUB standard_DHT( DH(,),DV(,) )
OPTION ARITHMETIC NATIVE
FOR j=0 TO 3
LET DH(0,j)=0
FOR i=1 TO 16
READ w$
LET DH(i,j)=BVAL(w$,16)
LET DH(0,j)=DH(0,j)+DH(i,j)
NEXT i
FOR i=0 TO DH(0,j)-1
READ w$
LET DV(i,j)=BVAL(w$,16)
NEXT i
NEXT j
! standard DHT
! ISO/IEC 10918-1:1993(E) Huffman table-specification examples
!
!--Y.DC (K.3)
DATA 00,01,05,01,01,01,01,01,01,00,00,00,00,00,00,00
DATA 00,01,02,03,04,05,06,07,08,09,0A,0B
!--Y.AC (K.5)
DATA 00,02,01,03,03,02,04,03,05,05,04,04,00,00,01,7D
DATA 01,02,03,00,04,11,05,12,21,31,41,06,13,51,61,07
DATA 22,71,14,32,81,91,A1,08,23,42,B1,C1,15,52,D1,F0
DATA 24,33,62,72,82,09,0A,16,17,18,19,1A,25,26,27,28
DATA 29,2A,34,35,36,37,38,39,3A,43,44,45,46,47,48,49
DATA 4A,53,54,55,56,57,58,59,5A,63,64,65,66,67,68,69
DATA 6A,73,74,75,76,77,78,79,7A,83,84,85,86,87,88,89
DATA 8A,92,93,94,95,96,97,98,99,9A,A2,A3,A4,A5,A6,A7
DATA A8,A9,AA,B2,B3,B4,B5,B6,B7,B8,B9,BA,C2,C3,C4,C5
DATA C6,C7,C8,C9,CA,D2,D3,D4,D5,D6,D7,D8,D9,DA,E1,E2
DATA E3,E4,E5,E6,E7,E8,E9,EA,F1,F2,F3,F4,F5,F6,F7,F8
DATA F9,FA
!--C.DC (K.4)
DATA 00,03,01,01,01,01,01,01,01,01,01,00,00,00,00,00
DATA 00,01,02,03,04,05,06,07,08,09,0A,0B
!--C.AC (K.6)
DATA 00,02,01,02,04,04,03,04,07,05,04,04,00,01,02,77
DATA 00,01,02,03,11,04,05,21,31,06,12,41,51,07,61,71
DATA 13,22,32,81,08,14,42,91,A1,B1,C1,09,23,33,52,F0
DATA 15,62,72,D1,0A,16,24,34,E1,25,F1,17,18,19,1A,26
DATA 27,28,29,2A,35,36,37,38,39,3A,43,44,45,46,47,48
DATA 49,4A,53,54,55,56,57,58,59,5A,63,64,65,66,67,68
DATA 69,6A,73,74,75,76,77,78,79,7A,82,83,84,85,86,87
DATA 88,89,8A,92,93,94,95,96,97,98,99,9A,A2,A3,A4,A5
DATA A6,A7,A8,A9,AA,B2,B3,B4,B5,B6,B7,B8,B9,BA,C2,C3
DATA C4,C5,C6,C7,C8,C9,CA,D2,D3,D4,D5,D6,D7,D8,D9,DA
DATA E2,E3,E4,E5,E6,E7,E8,E9,EA,F2,F3,F4,F5,F6,F7,F8
DATA F9,FA
!
END SUB
!-------------------
! make huffman tree
SUB TREE3
MAT Tr=ZER
FOR i=0 TO SE
LET F_(i)=S_(i,P) !数値を壊すので、コピー F_(i)で実行
NEXT i
LET F_(SE+1)=0 !← 空席用
!---minimum pair
DO
LET w=1e8
FOR i=0 TO SE+1 !←(+1) 符号木の最下に、空席を1つ作る。
IF F_(i)< w THEN
LET w=F_(i)
LET Ad1=i ! minimum1 !頻度最小の分岐アドレスAd1
END IF
NEXT i
LET w=1e8
FOR i=0 TO SE+1 !←(+1) 符号木の最下に、空席を1つ作る。
IF F_(i)< w AND i<>Ad1 THEN
LET w=F_(i)
LET Ad2=i ! minimum2 !頻度最小の分岐アドレスAd2
END IF
NEXT i
IF w=1e8 THEN EXIT DO !分岐の組が無くなるまで
!---
LET F_(Ad1)=F_(Ad1)+F_(Ad2) !次の頻度最小の組探しは、2分岐合計を1つにし、
LET
F_(Ad2)=1e9 !他方を外して行なう
!---
FOR Le1=16 TO 1 STEP
-1 !アドレスAd1の最上 節点レベルLe1 を探す(最初のLe1=0)
IF Tr(Le1,Ad1,1)>0 OR Tr(Le1,Ad1,3)>0 THEN EXIT FOR
NEXT Le1
FOR Le2=16 TO 1 STEP
-1 !アドレスAd2の最上 節点レベルLe2 を探す(最初のLe2=0)
IF Tr(Le2,Ad2,1)>0 OR Tr(Le2,Ad2,3)>0 THEN EXIT FOR
NEXT Le2
LET Le0=MAX( Le1,Le2 )+1 !両者何れよりも1つ上の節点レベル(Le0,Ad1)に、
!---
LET
Tr(Le0,Ad1,0)=Le1 !分岐先(
節点レベル,アドレス)として2組記入
LET Tr(Le0,Ad1,1)=Ad1
LET Tr(Le0,Ad1,2)=Le2
LET Tr(Le0,Ad1,3)=Ad2
LOOP
!---make DH()
LET k=0
CALL bitl(Le0,Ad1) !全アドレスの nested 段数を求める。
FOR Ad=0 TO SE !nested 段数が同じ Ad の総数を、段数毎に集計
LET DH(Tr(0,Ad,1),P)=DH(Tr(0,Ad,1),P)+1
NEXT Ad
LET DH(0,P)=Ad
END SUB
SUB bitl(Le,Ad) !最上 節点(Le0,Ad1)より全分岐を、底まで辿る
IF 0< Le THEN
LET k=k+1
CALL bitl( Tr(Le,Ad,0), Tr(Le,Ad,1) ) !分岐 nested 1
CALL bitl( Tr(Le,Ad,2), Tr(Le,Ad,3) ) !分岐 nested 2
LET k=k-1
ELSE
LET Tr(0,Ad,1)=k !最上 節点から底までの nested 段数kを書く
END IF
END SUB
LET cd$(0)="クラブ"
LET cd$(1)="ハート"
LET cd$(2)="スペード"
LET cd$(3)="ダイヤ"
! s$()(1:1) 先頭の数字= 1,0(裏,表)
LET s$( 0)="1ハート 8" ! 1:ハート 8
LET s$( 1)="1スペード 3" ! 2:スペード 3
LET s$( 2)="1ハート 6" ! 3:ハート 6
LET s$( 3)="1ダイア 9" ! 4:ダイア 9
LET s$( 4)="1ダイア 6" ! 5:ダイア 6
LET s$( 5)="0ダイア Q" !* 6:ダイア Q
LET s$( 6)="1ダイア J" ! 7:ダイア J
LET s$( 7)="0スペード Q" !* 8:スペード Q
LET s$( 8)="1ハート J" ! 9:ハート J
LET s$( 9)="1スペード 9" ! 10:スペード 9
LET s$(10)="0ハート 5" !*11:ハート 5
LET s$(11)="1ダイア 8" ! 12:ダイア 8
LET s$(12)="1スペード 6" ! 13:スペード 6
LET s$(13)="0ハート Q" !*14:ハート Q
LET s$(14)="0ダイア 7" !*15:ダイア 7
LET s$(15)="1スペード K" ! 16:スペード K
LET s$(16)="1クラブ K" ! 17:クラブ K
LET s$(17)="1ハート 9" ! 18:ハート 9
LET s$(18)="1ダイア 3" ! 19:ダイア 3
LET s$(19)="0ダイア 5" !*20:ダイア 5
LET s$(20)="0ダイア 10" !*21:ダイア 10
LET s$(21)="0スペード10" !*22:スペード10
LET s$(22)="1クラブ J" ! 23:クラブ J
LET s$(23)="1クラブ 9" ! 24:クラブ 9
LET s$(24)="0ハート 2" !*25:ハート 2
LET s$(25)="1ダイア A" ! 26:ダイア A
LET s$(26)="0スペード 5" !*27:スペード 5
LET s$(27)="0ハート 10" !*28:ハート 10
LET s$(28)="1スペード 8" ! 29:スペード 8
LET s$(29)="1クラブ 6" ! 30:クラブ 6
LET s$(30)="0ハート K" !*31:ハート K
LET s$(31)="0ダイア K" !*32:ダイア K
LET s$(32)="0スペード 4" !*33:スペード 4
LET s$(33)="0クラブ 10" !*34:クラブ 10
LET s$(34)="0クラブ 7" !*35:クラブ 7
LET s$(35)="1クラブ A" ! 36:クラブ A
LET s$(36)="0クラブ 2" !*37:クラブ 2
LET s$(37)="1ハート A" ! 38:ハート A
LET s$(38)="0スペード 2" !*39:スペード 2
LET s$(39)="0ハート 4" !*40:ハート 4
LET s$(40)="0スペード 7" !*41:スペード 7
LET s$(41)="0クラブ 4" !*42:クラブ 4
LET s$(42)="1クラブ 8" ! 43:クラブ 8
LET s$(43)="1クラブ 3" ! 44:クラブ 3
LET s$(44)="1ハート 3" ! 45:ハート 3
LET s$(45)="0ダイア 2" !*46:ダイア 2
LET s$(46)="0ダイア 4" !*47:ダイア 4
LET s$(47)="1スペード J" ! 48:スペード J
LET s$(48)="0クラブ Q" !*49:クラブ Q
LET s$(49)="0ハート 7" !*50:ハート 7
LET s$(50)="1スペード A" ! 51:スペード A
LET s$(51)="0クラブ 5" !*52:クラブ 5
FOR i=0 TO 52
LET A=MOD(i,52)
LET B=MOD(i+1,52)
LET C=MOD(i+2,52)
LET D=MOD(i+3,52)
LET E=MOD(i+4,52)
LET r=MOD(i+5,52)
LET sum= VAL(s$( A )(1:1))*8+VAL(s$( B )(1:1))*4+VAL(s$( E )(1:1))*2+VAL(s$( r )(1:1))
IF MOD(sum,5)=0 THEN
LET N=13
ELSEIF sum< 5 THEN
LET N=sum
ELSEIF 5< sum AND sum< 10 THEN
LET N=sum-1
ELSEIF 10< sum THEN
LET N=sum-2
END IF
PRINT "計算のカード:";cd$( VAL(s$( C )(1:1))*2+VAL(s$( D )(1:1)) );N
PRINT "最後のカード:";s$( r )(2:7)
PRINT
NEXT i
!●パターン1 段と右斜めが、行や列に置き換わる
LET N=6 !段数
DIM P(0 TO N,0 TO N) !2次元配列
MAT P=ZER
LET P(0,0)=1 !左詰め
FOR i=1 TO N
LET P(i,0)=1 !comb(n,n)=comb(n,0)=1
FOR j=1 TO i !comb(n,r)=comb(n-1,r-1)+comb(n-1,r)
LET P(i,j)=P(i-1,j-1)+P(i-1,j) !左上+上
NEXT j
NEXT i
MAT PRINT USING(REPEAT$("#### ",N+1)): P !※桁数が多い場合、#を増やす
PRINT
!例. パターン1の表探索によるΣ[k=1,N-1]{k}の計算
FOR k=1 TO N-1 !右斜め1番目の数列は「自然数」
PRINT "+";P(k,1);
NEXT k
PRINT "=";P(K,2) !右下(K=k+1)
!例. 円周上にN個の点を取り、互いに結線して分割される領域の数
FOR i=1 TO N+1
LET s=0
FOR k=0 TO 4 !左から5個まで
LET s=s+P(i-1,k)
NEXT k
PRINT i;"点="; s;"個"
NEXT i
!別解
DIM T(0 TO N)
FOR i=0 TO 4 !ベクトル(1,1,1,1,1,0,…)
LET T(i)=1
NEXT i
MAT T=P*T
MAT PRINT T;
!例. フィボナッチ数列
FOR i=0 TO N !右斜めの和
LET s=0
FOR j=0 TO i
LET s=s+P(i-j,j)
NEXT j
PRINT s;
NEXT i
PRINT
END
!●パターン2 左斜めと右斜めが、行や列に置き換わる
LET N=4 !段数
DIM P(0 TO N,0 TO N) !2次元配列
MAT P=ZER
FOR j=0 TO N !反時計まわりに45度回転
LET P(0,j)=1 !comb(n,n)=comb(n,0)=1
NEXT j
FOR i=1 TO N
LET P(i,0)=1 !comb(n,n)=comb(n,0)=1
FOR j=1 TO N-i !comb(n,r)=comb(n-1,r-1)+comb(n-1,r)
LET P(i,j)=P(i,j-1)+P(i-1,j) !左+上
NEXT j
NEXT i
MAT PRINT USING(REPEAT$("#### ",N+1)): P !※桁数が多い場合、#を増やす
PRINT
!例. N人をi個のグループに分ける場合の数
!
!3人で競走する場合
! 3人が1位 1通り(=comb(3,3))
! 2人が1位、1人が2位 3通り(=comb(3,2)*comb(1,1))
! 1人が1位、2人が2位 3通り(=comb(3,1)*comb(2,2))
! 1人が1位、1人が2位、1人が3位 6通り(=comb(3,1)*comb(2,1)*comb(1,1))
! したがって、13通り。
LET c=0
FOR i=0 TO N
LET r=0 !左斜めの和
FOR j=0 TO N-i
LET r=r+(-1)^j*P(i,j) !各段の左から偶数番目を負にする
NEXT j
LET c=c+r*i^N !重み
NEXT i
PRINT c
!別解
DIM B(0 TO N,0 TO N) !各段の左から偶数番目を負にする基本行列
MAT B=ZER
FOR i=0 TO N
LET B(i,i)=(-1)^i
NEXT i
MAT B=P*B
MAT PRINT B;
DIM T(0 TO N)
MAT T=CON !左斜めの数列を合計する
MAT T=B*T
DIM W(1,0 TO N) !重み 0^N,1~N,2^N,3^N,…
FOR i=0 TO N
LET W(1,i)=i^N
NEXT i
MAT PRINT W;
MAT T=W*T
MAT PRINT T; !=W*P*F*CON
!補足. N人をi個のグループに分ける場合の数
LET N=4 !人数
!指数型母関数を用いての解法
! 数列{a0,a1,a2,…,aN,…}に対して、この数列の指数型母関数G(x)は
! G(x)=a0*x^0/0!+a1*x^1/1!+a2*x^2/2!+ … +aN*x^N/N!+ …
!
!N人が順番の違うi個のグループに分かれてゴールしたものとし、各グループについて考える。
!場合の数(順列の数)を指数型計数子として表現すると
!グループ内はN人以下なら何人でも許され、その内での並び方は問題としないので
! x^0/0!+x^1/1!+x^2/2!+ … +x^N/N!+ … = EXP(x)
!しかし、グループ内には少なくとも1人はいるので
! x^1/1!+x^2/2!+ … +x^N/N!+ … = EXP(x)-1
!i個のグループでは指数型計数子は
! (EXP(x)-1)^i
! =Σ[j=0,i]{comb(i,j)*EXP(x)^(i-j)*(-1)^j} //二項定理
! =Σ[j=0,i]{comb(i,j)*(-1)^j*EXP((i-j)*x)} //EXP関数の指数部分をまとめる
! =Σ[j=0,i]{comb(i,j)*(-1)^j*Σ[N=0,∞]{(i-j)^N*x^N/N!}} //EXP関数を級数展開する
! =Σ[N=0,∞]{x^N/N!*Σ[j=0,i]{comb(i,j)*(-1)^j*(i-j)^N}}
!求める値は、x^N/N!の係数なので
! Σ[j=0,i]{comb(i,j)*(-1)^j*(i-j)^N}}
!j=iのとき、comb(i,j)*(-1)^j*(i-j)^N = 0 より
! Σ[j=0,i-1]{comb(i,j)*(-1)^j*(i-j)^N}}
!グループは、1〜Nまであるので
! Σ[i=1,N]{Σ[j=0,i-1]{comb(i,j)*(-1)^j*(i-j)^N}}}
LET f=0 !一般項 Σ[i=1,N]{Σ[j=0,i-1]{(-1)^j*comb(i,j*(i-j)^j}}
FOR i=1 TO N
FOR j=0 TO i-1
LET f=f+(-1)^j*comb(i,j)*(i-j)^N
NEXT j
NEXT i
PRINT f !結果を表示する
!上式を展開して、i^Nでまとめると
! Σ[i=1,N]{Σ[j=0,N-i]{(-1)^j*comb(i+j,j)*i^N}}
LET f=0 !一般項 Σ[i=1,N]{Σ[j=0,N-i]{(-1)^j*comb(i+j,j)*i^N}}
FOR i=1 TO N
FOR j=0 TO N-i
LET f=f+(-1)^j*comb(i+j,j)*i^N
NEXT j
NEXT i
PRINT f !結果を表示する
!この式をよく見ると、パスカルの三角形による解法へ
! :
! :
END
!別解
!A={a1,a2,a3,・・・,an}、B={b1,b2,b3,…,bm}のとき、AからBへの全射の数
! Σ[k=0,m]{(-1)^k*comb(m,k)*(m-k)^n}
!
!上式は、包除原理より求められる。
!求める値は、m=1〜nより。
! Σ[m=1,n]{Σ[k=0,m]{(-1)^k*comb(m,k)*(m-k)^n}}
LET n=5
LET f=0
FOR m=1 TO n
FOR k=0 TO m
LET f=f+(-1)^k*comb(m,k)*(m-k)^n
NEXT k
NEXT m
PRINT f
END
!順列 perm(n,r) 通りのパターンに、0 〜 perm(n,r)-1 の番号をつける方法
LET N=4 !1〜Nまでの数字を使う
LET R=4
DATA 1,2,3,4 !順列 PERM(N,N)=FACT(N) のテスト・データ
DATA 1,2,4,3
DATA 1,3,2,4
DATA 1,3,4,2
DATA 1,4,2,3
DATA 1,4,3,2
DATA 2,1,3,4
DATA 2,1,4,3
DATA 2,3,1,4
DATA 2,3,4,1
DATA 2,4,1,3
DATA 2,4,3,1
DATA 3,1,2,4
DATA 3,1,4,2
DATA 3,2,1,4
DATA 3,2,4,1
DATA 3,4,1,2
DATA 3,4,2,1
DATA 4,1,2,3
DATA 4,1,3,2
DATA 4,2,1,3
DATA 4,2,3,1
DATA 4,3,1,2
DATA 4,3,2,1
DIM A(R),B(R)
FOR d=1 TO PERM(N,R) !データを読み込む
MAT READ A
LET h=Perm2Num(A,N,R)
PRINT h !結果を表示する
CALL Num2Perm(h, B,N,R) !復元する
MAT PRINT B;
MAT PRINT A; !検算
NEXT d
END
!最小完全ハッシュ関数
EXTERNAL FUNCTION Perm2Num(A(),N,R) !順列パターンに番号を付ける ※辞書式順序
LET v=0
FOR j=1 TO R
LET t=A(j)
LET v=v+perm(N-j,R-j)*(t-1)
FOR k=j+1 TO R
IF A(k)>t THEN LET A(k)=A(k)-1
NEXT k
NEXT j
LET Perm2Num=v
END FUNCTION
EXTERNAL SUB Num2Perm(h, A(),N,R) !番号から順列パターンを生成する ※辞書式順序
LET v=h
FOR j=1 TO R
LET fac=perm(N-j,R-j)
LET t=INT(v/fac)
LET A(j)=t+1 !1〜N
LET v=v-fac*t
NEXT j
FOR j=R TO 1 STEP -1
FOR k=j+1 TO R
IF A(j)<=A(k) THEN LET A(k)=A(k)+1
NEXT k
NEXT j
END SUB
●組合せ型
!組合せ comb(n,r) 通りのパターンに、0 〜 comb(n,r)-1 の番号をつける方法
LET N=6 !1〜Nまでの数字を使う
LET R=3
DATA 1,2,3 !組合せ comb(6,3)=20 のテスト・データ
DATA 1,2,4 !※数字は小さい順
DATA 1,2,5
DATA 1,2,6
DATA 1,3,4
DATA 1,3,5
DATA 1,3,6
DATA 1,4,5
DATA 1,4,6
DATA 1,5,6
DATA 2,3,4
DATA 2,3,5
DATA 2,3,6
DATA 2,4,5
DATA 2,4,6
DATA 2,5,6
DATA 3,4,5
DATA 3,4,6
DATA 3,5,6
DATA 4,5,6
DIM A(R),B(R)
FOR d=1 TO comb(N,R) !データを読み込む
MAT READ A
LET h=Comb2Num(A,N,R)
PRINT h !結果を表示する
CALL Num2Comb(h, B,N,R) !復元する
MAT PRINT B;
MAT PRINT A; !検算
NEXT d
END
!最小完全ハッシュ関数
EXTERNAL FUNCTION Comb2Num(A(),N,R) !組合せパターンに番号を付ける ※辞書式順序
LET v=0
FOR i=R TO 1 STEP -1 !組合せをビット位置とする
LET t=N-A(i)
LET v=v+COMB(t,R-i+1)
NEXT i
LET Comb2Num=(comb(N,R)-1)-v
END FUNCTION
EXTERNAL SUB Num2Comb(h, A(),N,R) !番号から組合せパターンを生成する ※辞書式順序
LET v=comb(N,R)-h
LET m=R
FOR i=N-1 TO 0 STEP -1 !組合せをビット位置とする
LET t=COMB(i,m)
IF v>t THEN
LET A(R-m+1)=N-i !ビット位置(N-i-1)を1とする
LET m=m-1
LET v=v-t
END IF
NEXT i
END SUB
EXTERNAL FUNCTION Comb2Num2(A(),N,R) !組合せパターンに番号を付ける ※辞書式順序ではない
LET v=0
FOR i=R TO 1 STEP -1
LET t=A(i)-1 !組合せをビット位置とする
LET v=v+COMB(t,i)
NEXT i
LET Comb2Num2=v
END FUNCTION
EXTERNAL SUB Num2Comb2(h, A(),N,R) !番号から組合せパターンを生成する ※辞書式順序ではない
LET v=h
LET m=R
FOR i=N-1 TO 0 STEP -1 !組合せをビット位置とする
LET t=COMB(i,m)
IF t<=v THEN
LET A(m)=i+1 !ビット位置iを1とする
LET m=m-1
LET v=v-t
END IF
NEXT i
END SUB
100 DEF base(j)=2^MOD(j+2,3)+2^MOD(j+2,3)*10*(1-INT(j/3.01)) ! 11,22,44,1,2,4
110 FUNCTION change(p$)
120 IF UCASE$(p$)="R" THEN
130 LET c=0
140 ELSEIF UCASE$(p$)="B" THEN
150 LET c=1
160 ELSE
170 PRINT "ERROR-2 !!"
180 END IF
190 LET change=c
200 END FUNCTION
210 INPUT PROMPT "赤を""R"",黒を""B""とした文字列 = ":rb$ ! 例) brbbrr
220 IF LEN(rb$)<>6 THEN PRINT "ERROR-1 !!"
230 LET d=10
240 FOR j=1 TO 6
250 LET d=d+change(rb$(j:j))*base(j)
260 NEXT j
270 PRINT "解答 =";d
280 END
DIM base(6),dwn(6),check(6)
MAT READ base,dwn
FUNCTION number(q)
LET dd=10
FOR jj=1 TO 6
IF jj<>q THEN
LET dd=dd+check(jj)*base(jj)
ELSE
LET dd=dd+((check(jj)-1)^2)*base(jj)
END IF
NEXT jj
LET number=dd
END FUNCTION
FOR n=10 TO 94
MAT check=ZER
LET d=10
LET nn=n-d
FOR j=1 TO 6 ! baseの大きい数から引いていく
IF nn-base(dwn(j))>=0 THEN
LET check(dwn(j))=1
LET d=d+base(dwn(j))
LET nn=nn-base(dwn(j))
END IF
NEXT j
IF n=d THEN
LET check(1)=(check(1)-1)^2 ! 0,1の入れ換え
FOR j=1 TO 6
PRINT number(j);
NEXT j
PRINT
FOR j=1 TO 6
IF check(j)=0 THEN PRINT " 赤 "; ELSE PRINT " 黒 ";
NEXT j
PRINT
ELSE
PRINT n;" この数は生成できません"
END IF
NEXT n
DATA 11,22,44,1,2,4 ! base
DATA 3,2,1,6,5,4 ! baseの降順
END
DIM W(6) !重み
DATA 32,16,8,4,2,1 !正解 11,22,44,1,2,4
MAT READ W
!1列目 010101 0:赤、1:黒
100 DATA 1,1,0,1,0,1, 48 !客が答えた赤黒のパターン、思っていた数
DATA 0,0,0,1,0,1, 15
DATA 0,1,1,1,0,1, 81
DATA 0,1,0,0,0,1, 36
DATA 0,1,0,1,1,1, 39
DATA 0,1,0,1,0,0, 33
!2列目 011110
DATA 1,1,1,1,1,0, 90
DATA 0,0,1,1,1,0, 57
DATA 0,1,0,1,1,0, 35
DATA 0,1,1,0,1,0, 78
DATA 0,1,1,1,0,0, 77
DATA 0,1,1,1,1,1, 83
!3列目 100011
DATA 0,0,0,0,1,1, 16
DATA 1,1,0,0,1,1, 49
DATA 1,0,1,0,1,1, 71
DATA 1,0,0,1,1,1, 28
DATA 1,0,0,0,0,1, 25
DATA 1,0,0,0,1,0, 23
!4列目 101101
DATA 0,0,1,1,0,1, 59
DATA 1,1,1,1,0,1, 92
DATA 1,0,0,1,0,1, 26
DATA 1,0,1,0,0,1, 69
DATA 1,0,1,1,1,1, 72
DATA 1,0,1,1,0,0, 66
!5列目 001110
DATA 1,0,1,1,1,0, 68
DATA 0,1,1,1,1,0, 79
DATA 0,0,0,1,1,0, 13
DATA 0,0,1,0,1,0, 56
DATA 0,0,1,1,0,0, 55
DATA 0,0,1,1,1,1, 61
!6列目 110011
DATA 0,1,0,0,1,1, 38
DATA 1,0,0,0,1,1, 27
DATA 1,1,1,0,1,1, 93
DATA 1,1,0,1,1,1, 50
DATA 1,1,0,0,0,1, 47
DATA 1,1,0,0,1,0, 45
!7列目 111000
DATA 0,1,1,0,0,0, 76
DATA 1,0,1,0,0,0, 65
DATA 1,1,0,0,0,0, 43
DATA 1,1,1,1,0,0, 88
DATA 1,1,1,0,1,0, 89
DATA 1,1,1,0,0,1, 91
SET WINDOW -5,100,-5,100
DIM P(6)
FOR t=0 TO fact(6)-1 !重みの順列を生成する
CALL Num2Perm(t,P,6)
RESTORE 100
CLEAR
DRAW grid(10,10)
FOR d=1 TO 6*7 !サンプル・データより
DIM B(6) !客が答えた赤黒のパターン
MAT READ B
READ y !思っていた数
LET x=0 !線形写像
FOR i=1 TO 6
LET x=x+W(P(i))*B(i)
NEXT i
PLOT POINTS: x,y !より直線になるのが候補!
NEXT d
FOR i=1 TO 6 !重みの順列を表示する
PRINT W(P(i));
NEXT i
PRINT
WAIT DELAY 0.3 !※調整が必要
NEXT t
END
!n!の順列パターン ⇔ 0〜(n!-1)の番号
EXTERNAL FUNCTION Perm2Num(A(),N) !順列パターンに番号を付ける ※辞書式順序
LET v=0
FOR j=1 TO N-1 !※Nでは0
LET t=A(j)
LET v=v+fact(N-j)*(t-1)
FOR k=j+1 TO N
IF A(k)>t THEN LET A(k)=A(k)-1
NEXT k
NEXT j
LET Perm2Num=v
END FUNCTION
EXTERNAL SUB Num2Perm(h, A(),N) !番号から順列パターンを生成する ※辞書式順序
LET v=h
FOR j=1 TO N
LET fac=fact(N-j)
LET t=INT(v/fac)
LET A(j)=t+1 !1〜N
LET v=v-fac*t
NEXT j
FOR j=N TO 1 STEP -1
FOR k=j+1 TO N
IF A(j)<=A(k) THEN LET A(k)=A(k)+1
NEXT k
NEXT j
END SUB
!BMPファイル(圧縮なし)画像の部分領域(切り出し)を表示する
!参考 http://www.kk.iij4u.or.jp/~kondo/bmp/
OPTION CHARACTER byte
LET CX1=0 !切り出す画像領域の左上座標(ピクセル単位)
LET CY1=0
LET CX2=640 !右下座標
LET CY2=480
SET COLOR mode "NATIVE"
SET bitmap SIZE CX2-CX1,CY2-CY1 !スクリーン座標へ
SET WINDOW 0,CX2-CX1-1,CY2-CY1-1,0 !画面を画像サイズへ
SET POINT STYLE 1 !ドット形式
LET BFile$=REPEAT$(CHR$(0),14) !Dim BFile As BITMAPFILEHEADER
LET BInfo$=REPEAT$(CHR$(0),40) !Dim BInfo As BITMAPINFOHEADER
LET BPalt$=REPEAT$(CHR$(0),4) !Dim BPalt As RGBQUAD
file getname f$,"BMPファイル|*.BMP" !ファイル名を得る
IF f$="" THEN STOP
OPEN #1: NAME f$, ACCESS INPUT
LET cp=0 !読み込み現在位置
!---------- ファイルヘッダ部
LET p=0 !読み込み位置
CALL fseek(p) !Get #1,0,BFile ※VisualBasic
CALL fread(BFile$,p)
IF BFile$(1:2)="MB" THEN !BFile.bfType
PRINT "BMPファイルではありません。"
STOP
END IF
LET bfOffBits=CVI(BFile$,10,4) !BFile.bfOffBits
PRINT "bfOffBits=";bfOffBits
PRINT
!---------- 情報ヘッダ部(Windows Bitmap)
CALL fread(BInfo$,p) !Get #1, ,BInfo
LET biWidth=CVI(BInfo$,4,4) !BInfo.biWidth
PRINT "biWidth=";biWidth
LET biHeight=CVI(BInfo$,8,4) !BInfo.biHeight
PRINT "biHeight=";biHeight
LET biBitCount=CVI(BInfo$,14,2) !BInfo.biBitCount
PRINT "biBitCount=";biBitCount
LET biCompression=CVI(BInfo$,16,4) !BInfo.biCompression
PRINT "biCompression=";biCompression
PRINT
!---------- 情報ヘッダ部(パレット部)
DIM PAL(0 TO 255,4)
IF biBitCount<=8 THEN
FOR k=0 TO 2^biBitCount-1
CALL fread(BPalt$,p) !Get #1, ,BPalt
!!PRINT USING "### 番 ": k;
!!PRINT CVI2(BPalt$,0,1), !BPalt.rgbBlue ※符号なし
!!PRINT CVI2(BPalt$,1,1), !BPalt.rgbGreen
!!PRINT CVI2(BPalt$,2,1), !BPalt.rgbRed
!!PRINT CVI2(BPalt$,3,1) !BPalt.rgbReserved
LET PAL(k,3)=CVI2(BPalt$,0,1)/255 !BPalt.rgbBlue ※符号なし
LET PAL(k,2)=CVI2(BPalt$,1,1)/255 !BPalt.rgbGreen
LET PAL(k,1)=CVI2(BPalt$,2,1)/255 !BPalt.rgbRed
LET PAL(k,4)=CVI2(BPalt$,3,1)/255 !BPalt.rgbReserved
NEXT k
END IF
PRINT
IF biCompression<>0 THEN
PRINT "圧縮形式は未サポートです。"
STOP
END IF
!---------- 画像データ部
!SET DRAW mode hidden !ちらつき防止の開始
LET p=bfOffBits !ファイル内の画像データの先頭位置
CALL fseek(p)
LET L1=biWidth*biBitCount/8
LET L1b=(INT((L1-1)/4)+1)*4 !4バイト境界
FOR y=1 TO biHeight
LET BData$=REPEAT$(CHR$(0),L1b) !1行分の画像データ
CALL fread(BData$,p) !Get #1, ,BData
IF y>=biHeight-CY2 AND y<=biHeight-CY1 THEN !切り出し領域内なら ※下から格納されている
SELECT CASE biBitCount
CASE 1 !2色
FOR x=MAX(INT((CX1-1)/8),0) TO L1b-1 !1行分の画像データ(切り出し領域内左端から)
!!PRINT "(";8/biBitCount*x+1;",";y;")",
LET b=CVI2(BData$,x,1)
!!!PRINT right$("0000000"&BSTR$(b,2),8)
LET t$=right$("0000000"&BSTR$(b,2),8)
LET bb=1
DO UNTIL bb>8
LET xx=x*8+bb-1
IF xx>CX2 THEN EXIT FOR !切り出し領域内右端なら
IF xx>=CX1 THEN
IF xx<=biWidth THEN
LET t=VAL(t$(bb:bb))
SET POINT COLOR colorindex(PAL(t,1),PAL(t,2),PAL(t,3))
PLOT POINTS: xx - CX1, biHeight-y - CY1 !※下から格納されている
END IF
END IF
LET bb=bb+1
LOOP
NEXT x
CASE 4 !16色
FOR x=MAX(INT((CX1-1)/2),0) TO L1b-1 !1行分の画像データ(切り出し領域内左端から)
!!PRINT "(";8/biBitCount*x+1;",";y;")",
LET b=CVI2(BData$,x,1)
!!PRINT INT(b/16); !上4bit
!!PRINT MOD(b,16) !下4bit
LET xx=8/biBitCount*x+1
IF xx>CX2 THEN EXIT FOR !切り出し領域内右端なら
IF xx>=CX1 THEN
IF xx<=biWidth THEN
LET t=INT(b/16) !上4bit
SET POINT COLOR colorindex(PAL(t,1),PAL(t,2),PAL(t,3))
PLOT POINTS: xx - CX1, biHeight-y - CY1 !※下から格納されている
END IF
END IF
IF xx+1>CX2 THEN EXIT FOR !切り出し領域内なら
IF xx+1>=CX1 THEN
IF xx<=biWidth THEN
LET t=MOD(b,16) !下4bit
SET POINT COLOR colorindex(PAL(t,1),PAL(t,2),PAL(t,3))
PLOT POINTS: xx+1 - CX1, biHeight-y - CY1 !※下から格納されている
END IF
END IF
NEXT x
CASE ELSE !256色、24ビット色、32ビット色
FOR x=MAX(CX1,1) TO MIN(CX2,biWidth) !切り出し領域内
LET t=(x-1)*biBitCount/8
!!PRINT "(";x;",";y;")",
!!FOR k=0 TO biBitCount/8-1
!! PRINT CVI2(BData$,t+k,1); !BData ※符号なし
!!NEXT k
!!PRINT
IF biBitCount=8 THEN !256色なら
LET tt=CVI2(BData$,t+0,1)
SET POINT COLOR colorindex(PAL(tt,1),PAL(tt,2),PAL(tt,3))
ELSE
LET bb=CVI2(BData$,t+0,1) !BData ※符号なし
LET gg=CVI2(BData$,t+1,1)
LET rr=CVI2(BData$,t+2,1)
SET POINT COLOR colorindex(rr/255,gg/255,bb/255)
END IF
PLOT POINTS: x - CX1, biHeight-y - CY1 !※下から格納されている
NEXT x
END SELECT
END IF
NEXT y
!SET DRAW mode explicit !ちらつき防止の終了
CLOSE #1
!ファイル関連
SUB fseek(p) !読み込み位置を設定する
IF p<cp THEN !前へ
SET #1: POINTER BEGIN
LET cp=0
END IF
FOR i=1 TO p-cp !skip it
CHARACTER INPUT #1: tmp$
NEXT i
LET cp=p !現在位置の更新
END SUB
SUB fread(r$,p) !レコードを読み込む
FOR i=1 TO LEN(r$) !read it
CHARACTER INPUT #1: r$(i:i)
NEXT i
LET p=p+LEN(r$) !現在位置の更新
LET cp=p
END SUB
END
EXTERNAL FUNCTION CVI(s$,p,m) !文字列に埋め込まれたm*8ビット符号付き整数を取り出す
OPTION CHARACTER byte
LET n=0
FOR i=1 TO m
LET n=n+256^(i-1)*ORD(s$(p+i:p+i))
NEXT i
IF n<2^(m*8-1) THEN LET CVI=n ELSE LET CVI=n-2^(m*8)
END FUNCTION
EXTERNAL FUNCTION CVI2(s$,p,m) !文字列に埋め込まれたm*8ビット符号なし整数を取り出す
OPTION CHARACTER byte
LET n=0
FOR i=1 TO m
LET n=n+256^(i-1)*ORD(s$(p+i:p+i))
NEXT i
LET CVI2=n
END FUNCTION
OPTION ARITHMETIC NATIVE
SET COLOR mode "NATIVE"
OPTION BASE 0
DIM D(1000,1000)
ASK directory currentD$
!
SET directory "C:\WINDOWS\デスクトップ" !最初に開くdirectory(削除:マイドキュメント)
FILE GETNAME file$, "BMP"
IF file$="" THEN
PRINT "入力ファイル名無しで、中止。"
STOP
END IF
PRINT "入力ファイル:"& file$
!
!---原画をロード、グラフ座標を、左上から右下方向へ画素単位に設定
gload file$
ASK PIXEL SIZE xw,yw
SET WINDOW 0,xw,yw,0
PRINT xw+1;"*";yw+1;"画素の原画"
!
!---原画から、切出したい画素の範囲を書く
LET X0=10 !左
LET Y0=20 !上
LET X1=200 !右
LET Y1=200 !下
!
!---切り出し
MAT D=ZER(X1-X0,Y1-Y0)
ASK PIXEL ARRAY (X0,Y0) D
!
!---切り出し画像の表示
SET bitmap SIZE X1-X0+1,Y1-Y0+1
MAT PLOT CELLS,IN 0,1;1,0 :D
PRINT "(";X0;",";Y0;")から、";"(";X1;",";Y1;")までの切り出し画像"
!
!---切り出し画像の保存と、再表示
SET directory currentD$
gsave "sample.bmp"
gload "sample.bmp"
SET bitmap SIZE 501,501
!●パターン2 左斜めと右斜めが、行と列に置き換わる
!※格子状経路の経路の数などを求める場合など、配列全体を埋めておくのがよい。
LET M=20 !行
LET N=6 !列
DIM P(0 TO M,0 TO N) !2次元配列
MAT P=ZER
FOR j=0 TO N !反時計まわりに45度回転
LET P(0,j)=1 !comb(n,n)=comb(n,0)=1
NEXT j
FOR i=1 TO M
LET P(i,0)=1 !comb(n,n)=comb(n,0)=1
FOR j=1 TO N !comb(n,r)=comb(n-1,r-1)+comb(n-1,r)
LET P(i,j)=P(i,j-1)+P(i-1,j) !左+上 ※表計算Excelでは、オートフィル機能
NEXT j
NEXT i
MAT PRINT USING(REPEAT$("###### ",N+1)): P !※桁数が多い場合、#を増やす
PRINT
!例. 連続する自然数の積和
! 1*2+2*3+3*4+ … +n*(n+1)=Σ[k=1,n]{k*(k+1)}
! 1*2*3+2*3*4+3*4*5+ … +n*(n+1)*(n+2)=Σ[k=1,n]{k*(k+1)*(k+2)}
! :
! :
!
! comb(n,r)=n*(n-1)*(n-2)* … *(n-r+1)/r!より、r!*comb(n+r-1,r)=n*(n+1)*(n+2)* … *(n+r-1)
!
!パスカルの三角形では、
! ↓R
! comb(n-1,0) comb(n,1) comb(n+1,2) comb(n+2,3) comb(n+4,4) …
! 1 1 1 1 1
! 1 2 3 4 5
! 1 3 6 10 15
! 1 4 10 N-1 → 20 35
! 1 5 15 35 70
! 1 6 21 56 126
! 1 7 28 84 210
!
! 右斜めr段の数列 comb(n+(r-1),r) の和は、r+1段。
LET N=15
LET R=2 !2つの場合
PRINT fact(R)*P(N-1,R+1)
LET s=0 !検算
FOR k=1 TO N
LET s=s+k*(k+1) !Σ[k=1,n]{k*(k+1)}
NEXT k
PRINT s
END
!●7^2009の下4桁
OPTION ARITHMETIC RATIONAL !多桁整数
!7*7=49=50-1より、7^2000=(50-1)^1000
!これを二項定理で展開すると、
! 項 comb(1000,r)*50^r*(-1)^(1000-r)、r=0,1,2,3,…
!の和となる。
!r=4以上、50^rが10000で割り切れるから、下4桁はすべて0となる。
LET s=0
!r=3,2,1,0のとき
FOR r=3 TO 0 STEP -1
LET s=s + comb(1000,r)*50^r*(-1)^(1000-r)
NEXT r
PRINT MOD(s*7^9,10^5) !残り7^9を加味して
END
PRINT "--- パリティ 行列 h"
MAT READ h
DATA 0,0,0,1 ! 1 ! 0 は エラー無しの予約値。
DATA 0,0,1,0 ! 2
DATA 0,0,1,1 ! 3
DATA 0,1,0,0 ! 4
DATA 0,1,0,1 ! 5
DATA 0,1,1,0 ! 6
DATA 0,1,1,1 ! 7
DATA 1,0,0,0 ! 8
DATA 1,0,0,1 ! 9
DATA 1,0,1,0 ! 10
DATA 1,0,1,1 ! 11
DATA 1,1,0,0 ! 12
DATA 1,1,0,1 ! 13
DATA 1,1,1,0 ! 14 !オール1の、15 も使用できない。(※注)
LET M(1,11)=MOD( M(1,4)+M(1,5)+M(1,6)+M(1,7)+M(1,8)+M(1,9)+M(1,10) ,2)
LET M(1,12)=MOD( M(1,1)+M(1,2)+M(1,4)+M(1,7)+M(1,9)+M(1,10) ,2)
LET M(1,13)=MOD( M(1,1)+M(1,3)+M(1,4)+M(1,6)+M(1,8)+M(1,10) ,2)
LET M(1,14)=MOD( M(1,2)+M(1,3)+M(1,4)+M(1,5)+M(1,8)+M(1,9) ,2)
!-----エラー・ビットを、順番に置いてみる。0:エラー無しから1〜14まで
FOR j=0 TO 14
CALL error(j)
NEXT j
SUB error(j)
PRINT "-------------------------------------"
PRINT "原形のメッセージ・データー"
MAT PRINT M;
IF j<>0 THEN
LET back=M(1,j)
PRINT "左から";j;"番目のビットが、反転すると"
IF M(1,j)=1 THEN LET M(1,j)=0 ELSE LET M(1,j)=1
ELSE
PRINT "全ビット反転なければ、"
END IF
MAT PRINT M;
!---
CALL check
!---
PRINT "チェック・データーも";bcc(1,1)*8+bcc(1,2)*4+bcc(1,3)*2+bcc(1,4);"になる。2進数"
MAT PRINT bcc;
IF j<>0 THEN LET M(1,j)=back !元へ戻す
END SUB
SUB check
MAT bcc=M*h
FOR i=1 TO 4
LET bcc(1,i)=MOD( bcc(1,i), 2)
NEXT i
END SUB
!虫食い算
! □□□ ← i 被乗数
! x□□□ ← j 乗数
! --------
! □□□ ← a 途中結果1
! □□□ ← b 途中結果2
!□□□ ← c 途中結果3
!----------
!□□□□□ ← d 結果
LET t0=TIME
DEF fnFIG(x,n)=MOD(INT(x/10^n),10) !n桁目の数を得る ※0:一の位、1:十の位、2:百の位、…
LET ANSWER_COUNT=0 !解答数
DIM nm(0 TO 9),nm_sav(0 TO 9) !0〜9の数字の重複を確認する
FOR i=100 TO 999 !被乗数
MAT nm=ZER
FOR k=0 TO 2 !重複チェック ※2つずつ
LET t=fnFIG(i,k) !各桁の数字を得る
IF nm(t)=2 THEN GOTO 200 !既に2つある!
LET nm(t)=nm(t)+1
NEXT k
FOR j=100 TO 999 !乗数
MAT nm_sav=nm !save it
FOR k=0 TO 2 !重複チェック
LET t=fnFIG(j,k)
IF nm(t)=2 THEN GOTO 100
LET nm(t)=nm(t)+1
NEXT k
LET a=i*MOD(j,10) !乗数の一の位との積
IF a<100 OR a>999 THEN GOTO 100 !途中結果1は3桁の数?
FOR k=0 TO 2 !重複チェック
LET t=fnFIG(a,k)
IF nm(t)=2 THEN GOTO 100
LET nm(t)=nm(t)+1
NEXT k
LET b=i*MOD(INT(j/10),10) !乗数の十の位との積
IF b<100 OR b>999 THEN GOTO 100 !途中結果2は3桁の数?
FOR k=0 TO 2 !重複チェック
LET t=fnFIG(b,k)
IF nm(t)=2 THEN GOTO 100
LET nm(t)=nm(t)+1
NEXT k
LET c=i*INT(j/100) !乗数の百の位との積
IF c<100 OR c>999 THEN GOTO 100 !途中結果3は3桁の数?
FOR k=0 TO 2 !重複チェック
LET t=fnFIG(c,k)
IF nm(t)=2 THEN GOTO 100
LET nm(t)=nm(t)+1
NEXT k
LET d=i*j !被乗数*乗数=乗算結果
IF d<10000 OR d>99999 THEN GOTO 100 !結果は5桁の数?
FOR k=0 TO 4 !重複チェック
LET t=fnFIG(d,k)
IF nm(t)=2 THEN GOTO 100
LET nm(t)=nm(t)+1
NEXT k
LET ANSWER_COUNT=ANSWER_COUNT+1 !解答数
PRINT "No.";ANSWER_COUNT
PRINT USING " ###":i !結果の表示
PRINT USING "×###":j
PRINT "-----"
PRINT USING " ###":a
PRINT USING " ### ":b
PRINT USING "### ":c
PRINT "-----"
PRINT USING "#####":d
PRINT
100 !continue
MAT nm=nm_sav !restore it
NEXT j
200 !continue
NEXT i
PRINT "計算時間=";TIME-t0
END
!グッドスタインの定理(R.L.Goodstein)
!ウィキペディアより
!http://www.cwi.nl/~tromp/pearls.html#goodstein のRuby版を移植
FUNCTION s(b,e,n)
IF n=0 THEN LET s=0 ELSE LET s=MOD(n,b)*(b+1)^s(b,0,e)+s(b,e+1,INT(n/b))
END FUNCTION
FUNCTION g(b,n)
IF n=0 THEN LET g=b ELSE LET g=g(b+1,s(b,0,n)-1)
END FUNCTION
DEF f(n)=g(2,n) !自然数nに対する0になるときの底を返す
PRINT f(0) !f(0)=2,f(1)=3,f(2)=5,f(3)=7
PRINT f(1)
PRINT f(2)
PRINT f(3)
PRINT f(4) !f(4)=3*2^402653211-1 ※スタック・オーバーフロー
END
LET t0=TIME
LET N=9 !枚数
DIM P(N) !1〜Nまでのカード
LET cmax=0
FOR i=N*fact(N-2) TO fact(N)-1 !順列を生成する ※0〜N*(N-2)!-1番目の順列は、1*****、21****
!FOR i=0 TO fact(N)-1 !順列を生成する
CALL Num2Perm(i, P,N)
!!!MAT PRINT P; !debug
LET c=0 !回数
DO UNTIL P(1)=1 !トップのカードが「1」まで
CALL reverse(P,(P(1))) !トップのカードの数字だけカードを抜き出し、順番を逆にして元に戻す
LET c=c+1
LOOP
!!!PRINT "回数=";c !debug
IF c>cmax THEN !最大のものを記録する
LET cmax=c
LET i_sav=i
END IF
NEXT i
PRINT "最大の回数=";cmax
CALL Num2Perm(i_sav, P,N) !順列を再現する
MAT PRINT P;
PRINT "計算時間=";TIME-t0
END
EXTERNAL SUB reverse(A(),N) !1〜Nまでの並びを逆順にする
FOR i=1 TO INT(N/2) !交換位置は半分まで ※全部すると元に戻る
swap A(i),A(N-i+1) !中央から対称な位置どうし
NEXT i
END SUB
EXTERNAL SUB Num2Perm(h, A(),N) !番号から順列パターンを生成する ※辞書式順序
LET v=h
FOR j=1 TO N
LET fac=fact(N-j)
LET t=INT(v/fac)
LET A(j)=t+1 !1〜N
LET v=v-fac*t
NEXT j
FOR j=N-1 TO 1 STEP -1
FOR k=j+1 TO N
IF A(j)<=A(k) THEN LET A(k)=A(k)+1
NEXT k
NEXT j
END SUB
LET t0=TIME
LET N=13 !1〜Nのカード
DIM P(N)
FOR i=1 TO N !完全整列 1,2,3,4,…
LET P(i)=i
NEXT i
LET cmax=0 !最多手数
DIM P_sav(N) !その並び
MAT P_sav=P
CALL try(P,N,0,cmax,P_sav)
PRINT "最大の回数=";cmax
MAT PRINT P_sav;
PRINT "計算時間=";TIME-t0
END
EXTERNAL SUB reverse(A(),N) !1〜N番目までの並びを逆順にする
FOR i=1 TO INT(N/2) !交換位置は半分まで ※全部すると元に戻る
swap A(i),A(N-i+1) !中央から対称な位置どうし
NEXT i
END SUB
EXTERNAL SUB try(P(),N,c,cmax,P_sav())
DIM W(N)
MAT W=P
FOR i=2 TO N !交換できなくなるまで
MAT P=W
IF P(i)=i THEN !i番目のカードが数字iなら交換可能! ※逆の操作
CALL reverse(P,i) !トップのカードの数字だけカードを抜き出し、順番を逆にして元に戻す
IF c+1>cmax THEN !最大のものを記録する
LET cmax=c+1
MAT P_sav=P
END IF
CALL try(P,N,c+1,cmax,P_sav) !次へ
END IF
NEXT i
END SUB
!WindowsMe、Pentium��700MHz、192MBにて、十進BASIC 2進モードで実行。
!
!最大の回数= 80
! 2 9 4 5 11 12 10 1 8 13 3 6 7
!
!計算時間= 1528.79 ←約25.5分
!虫食い算
! a 除数 □□8□□ ← b 商
! ------------------
! □□ )□□□□□□□ ← c 被除数
! □□□ ← d
! ----------
! □□ ← e
! □□ ← f
! ----------
! □□□ ← g
! □□□ ← h
! --------
! 4 ← 余り
LET t0=TIME
DEF fnFIG(x,n)=MOD(INT(x/10^n),10) !n桁目の数を得る ※0:一の位、1:十の位、2:百の位、…
LET ANSWER_COUNT=0 !解答数
FOR a=10 TO 99 !除数
FOR b=10000 TO 99999 !商
IF fnFIG(b,2)<>8 THEN GOTO 100 !商の百の位は8か?
LET c=b*a + 4 !※余りを加算する
IF c<1000000 OR c>9999999 THEN GOTO 100 !被除数cは7桁の数?
LET d=fnFIG(b,4)*a !途中結果d
IF d<100 OR d>999 THEN GOTO 100 !3桁の数?
LET w=INT(c/10000) !※筆算を参照
LET e=(w-d)*100+fnFIG(c,3)*10+fnFIG(c,2) !途中結果e
IF e<10 OR e>99 THEN GOTO 100 !2桁の数?
LET f=fnFIG(b,2)*a !途中結果f
IF f<10 OR f>99 THEN GOTO 100 !2桁の数?
LET g=(e-f)*100+fnFIG(c,1)*10+fnFIG(c,0) !途中結果g
IF g<100 OR g>999 THEN GOTO 100 !3桁の数?
LET h=fnFIG(b,0)*a !途中結果h
IF h<100 OR h>999 THEN GOTO 100 !3桁の数?
IF g-h<>4 THEN GOTO 100 !余りは4か?
LET ANSWER_COUNT=ANSWER_COUNT+1 !解答数
PRINT "No.";ANSWER_COUNT
!結果の表示
PRINT USING " #####": b !商
PRINT " -----------"
PRINT USING " ## ) #######": a,c !除数、被除数
PRINT USING " ###": d
PRINT " -----"
PRINT USING " ##": e
PRINT USING " ##": f
PRINT " ----"
PRINT USING " ###": g
PRINT USING " ###": h
PRINT " ------"
PRINT " 4"
PRINT
100 !continue
NEXT b
200 !continue
NEXT a
PRINT "計算時間=";TIME-t0
END
LET t0=TIME
DEF fnFIG(x,n)=MOD(INT(x/10^n),10) !n桁目の数を得る ※0:一の位、1:十の位、2:百の位、…
LET N=9 !1〜9の数字
LET R=3 !左辺の桁数
DIM P(R),NM(0 TO 9)
FOR i=0 TO perm(N,R)-1
CALL Num2Perm(i, P,N,R) !左辺を算出する
LET x=0
FOR k=1 TO R !ホーナー法
LET x=x*10+P(k)
NEXT k
LET y=x*x !右辺を算出する ※x^2=yより
MAT NM=ZER !重複していないか確認する
LET NM(0)=1 !0
FOR k=1 TO R !左辺側
LET NM(P(k))=1 !使用中
NEXT k
FOR k=0 TO N-R-1 !右辺側
LET t=fnFIG(y,k)
IF NM(t)=1 THEN EXIT FOR !重複!
LET NM(t)=1
NEXT k
IF k>N-R-1 THEN PRINT x;"^ 2 =";y !結果を表示する
NEXT i
PRINT "計算時間=";TIME-t0
END
EXTERNAL SUB Num2Perm(h, A(),N,R) !番号から順列パターンを生成する ※辞書式順序
LET v=h
FOR j=1 TO R
LET fac=PERM(N-j,R-j)
LET t=INT(v/fac)
LET A(j)=t+1 !1〜N
LET v=v-fac*t
NEXT j
FOR j=R-1 TO 1 STEP -1
FOR k=j+1 TO R
IF A(j)<=A(k) THEN LET A(k)=A(k)+1
NEXT k
NEXT j
END SUB
その他の例
分数小町
□□□□/□□□□□=1/○ ただし、□は1〜9が1個ずつ、○は2〜9
ヒント 9! → 4!。 分母=○×分子。
●平方小町
□□□□□□□□□=○○○○○^2 ただし、□は1〜9が1個ずつ、○は0〜9
LET t0=TIME
DEF fnFIG(x,n)=MOD(INT(x/10^n),10) !n桁目の数を得る ※0:一の位、1:十の位、2:百の位、…
LET N=9 !1〜9の数字
DIM NM(0 TO 9)
FOR i=INT(SQR(123456789)) TO INT(SQR(987654321))
LET x=i*i !右辺を算出する ※x=i^2より
MAT NM=ZER !重複していないか確認する
LET NM(0)=1
FOR k=1 TO N !左辺側
LET t=fnFIG(x,k-1)
IF NM(t)=1 THEN EXIT FOR !重複!
LET NM(t)=1
NEXT k
IF k>N THEN PRINT x;"=";i;"^ 2" !結果を表示する
NEXT i
PRINT "計算時間=";TIME-t0
END
!アラビア数字(1,2,3,…)を漢数字(一,二,三,…)に変換する(Excel準拠)
LET n1$="〇一二三四五六七八九" !漢数字
LET f1$="千百十 " !位
LET f2$="垓京兆億万 " !4桁ずつの位
LET n2$="〇壱弐参四伍六七八九" !大字
LET f3$="阡百拾 " !位
LET f4$="垓京兆億萬 " !4桁ずつの位
LET n3$="0123456789" !数字
FUNCTION NumberString$(x,p) !アラビア数字(1,2,3,…)を漢数字(一,二,三,…)に変換する
IF x<0 OR x<>INT(x) THEN
PRINT "非負の整数ではありません。"; x
STOP
ELSE
LET w$=""
SELECT CASE p
CASE 1 !漢数字で表記する
LET a=x
IF a=0 THEN
LET w$="〇"
ELSE
LET i=LEN(f2$)
DO UNTIL a=0 !上位の数字がなくなるまで
LET aa=MOD(a,10000) !「…兆億万 」の4桁ずつ
IF aa<>0 THEN
LET ww$=f2$(i:i)
IF ww$<>" " THEN LET w$=ww$&w$
LET k=LEN(f1$)
DO UNTIL aa=0 !各「千百十 」の位
LET ww$=f1$(k:k)
IF ww$=" " THEN LET ww$=""
LET t=MOD(aa,10) !一の位から
IF t=0 THEN !ゼロ・サプレス
ELSEIF k<LEN(f1$) AND t=1 THEN !1・サプレス
LET w$=ww$&w$
ELSE
LET w$=n1$(t+1:t+1)&ww$&w$
END IF
LET aa=INT(aa/10) !次へ
LET k=k-1
LOOP
END IF
LET a=INT(a/10000) !次へ
LET i=i-1
LOOP
END IF
CASE 2 !大字の漢数字で表記する
LET a=x
IF a=0 THEN
LET w$="〇"
ELSE
LET i=LEN(f4$)
DO UNTIL a=0 !上位の数字がなくなるまで
LET aa=MOD(a,10000) !「…兆億万 」の4桁ずつ
IF aa<>0 THEN
LET ww$=f4$(i:i)
IF ww$<>" " THEN LET w$=ww$&w$
LET k=LEN(f3$)
DO UNTIL aa=0 !各「千百十 」の位
LET ww$=f3$(k:k)
IF ww$=" " THEN LET ww$=""
LET t=MOD(aa,10) !一の位から
IF t=0 THEN !ゼロ・サプレス
!!!ELSEIF k<LEN(f3$) AND t=1 THEN !1・サプレス
!!! LET w$=ww$&w$
ELSE
LET w$=n2$(t+1:t+1)&ww$&w$
END IF
LET aa=INT(aa/10) !次へ
LET k=k-1
LOOP
END IF
LET a=INT(a/10000) !次へ
LET i=i-1
LOOP
END IF
CASE 3 !数値をそのまま漢数字で表記する
LET a=x
IF a=0 THEN
LET w$="0"
ELSE
DO UNTIL a=0 !上位の桁がなくなるまで
LET t=MOD(a,10)+1 !一の位から
LET w$=n1$(t:t)&w$
LET a=INT(a/10) !次へ
LOOP
END IF
CASE 4 !十,百,千,万などを漢数字で表記する
LET a=x
IF a=0 THEN
LET w$="〇"
ELSE
LET i=LEN(f2$)
DO UNTIL a=0 !上位の数字がなくなるまで
LET aa=MOD(a,10000) !「…兆億万 」の4桁ずつ
IF aa<>0 THEN
LET ww$=f2$(i:i)
IF ww$<>" " THEN LET w$=ww$&w$
LET k=LEN(f1$)
DO UNTIL aa=0 !各「千百十 」の位
LET ww$=f1$(k:k)
IF ww$=" " THEN LET ww$=""
LET t=MOD(aa,10) !一の位から
IF t=0 THEN !ゼロ・サプレス
ELSEIF k<LEN(f1$) AND t=1 THEN !1・サプレス
LET w$=ww$&w$
ELSE
LET w$=n3$(t+1:t+1)&ww$&w$
END IF
LET aa=INT(aa/10) !次へ
LET k=k-1
LOOP
END IF
LET a=INT(a/10000) !次へ
LET i=i-1
LOOP
END IF
CASE ELSE
END SELECT
LET NumberString$=w$ !結果を返す
END IF
END FUNCTION
!!!PRINT NumberString$(1732050807568877,2) !※1000桁モード、有理数モード
PRINT NumberString$(1234567890,1) !十二億三千四百五十六万七千八百九十
PRINT NumberString$(1234567890,2) !壱拾弐億参阡四百伍拾六萬七阡八百九拾
PRINT NumberString$(1234567890,3) !一二三四五六七八九〇
PRINT NumberString$(1234567890,4) !十2億3千4百5十6万7千8百9十
END
!ベッセル関数ですが、このリストは、xの範囲が、実数までで、
!複素数が使用できません。拡張できる方、お願いします。
!
!※十進BASIC にも ベッセル関数、変形ベッセル関数1種を内包出来ないでしょうか。
!-------------------------------
OPTION ARITHMETIC NATIVE
OPTION BASE 0
SET TEXT background "opaque"
DIM col(5)
MAT READ col
DATA 4,10,2, 8,8,8 !Red darkGreen Blue Gray Gray Gray
SUB window_i
CLEAR
LET h=4
LET l=-1.5
LET xr=4
SET WINDOW -.1*xr,xr, l,h
DRAW grid(xr/8,h/8)
ASK PIXEL SIZE (0,0; xr,0) j,i
LET dx=xr/j !pitch
END SUB
SUB window_j
CLEAR
LET h=1
LET l=-1
LET xr=20
SET WINDOW -.1*xr,xr, l,h
DRAW grid(xr/4,h/5)
ASK PIXEL SIZE (0,0; xr,0) j,i
LET dx=xr/j !pitch
END SUB
!-------
SUB G_besseli
FOR n=0 TO 2
SET LINE COLOR col(n)
SET TEXT COLOR col(n)
PLOT TEXT,AT .13*xr,h-.08*(h-l)-.04*(h-l)*n :"変形ベッセル関数1種 "& STR$(n)& "次"
FOR x=dx TO xr+dx STEP dx
LET y=besseli(n,x)
PLOT LINES: x,y; ! PEN-on
IF FP(x)< dx THEN PRINT USING"##.## ###.######":x,y
NEXT x
PLOT LINES !PEN-off
PRINT
NEXT n
END SUB
SUB G_besselj
FOR n=0 TO 2
SET LINE COLOR col(n)
SET TEXT COLOR col(n)
PLOT TEXT,AT .13*xr,h-.08*(h-l)-.04*(h-l)*n :"ベッセル関数1種 "& STR$(n)& "次"
FOR x=dx TO xr+dx STEP dx
LET y=besselj(n,x)
PLOT LINES: x,y; ! PEN-on
IF FP(x)< dx THEN PRINT USING"##.## ###.######":x,y
NEXT x
PLOT LINES !PEN-off
PRINT
NEXT n
END SUB
!-------
FUNCTION besseli(n,x)
LET m=2*INT( (6+MAX(n,1.5*x)+9*1.5*x/(1.5*x+2))/2)
LET w=0
FOR k=1 TO m
LET w=w+Tki(k)
NEXT k
LET besseli=EXP(x)*Tki(n)/(Tki(0)+2*w)
END FUNCTION
FUNCTION Tki(i)
LET t2=0
LET t1=1e-9
LET t0=2*(m+1)/x*t1+t2
FOR kp1=m TO i+1 STEP -1
LET t2=t1
LET t1=t0
LET t0=2*kp1/x*t1+t2
NEXT kp1
LET Tki=t0
END FUNCTION
!-------
FUNCTION besselj(n,x)
LET m=2*INT( (6+MAX(n,1.5*x)+9*1.5*x/(1.5*x+2))/2)
LET w=0
FOR k=1 TO m/2
LET w=w+Tk(k*2)
NEXT k
LET besselj=Tk(n)/(Tk(0)+2*w)
END FUNCTION
FUNCTION Tk(i)
LET t2=0
LET t1=1e-9
LET t0=2*(m+1)/x*t1-t2
FOR kp1=m TO i+1 STEP -1
LET t2=t1
LET t1=t0
LET t0=2*kp1/x*t1-t2
NEXT kp1
LET Tk=t0
END FUNCTION
!辞書式順序で次の順列を返す
LET N=4
DIM A(N)
DATA 1,2,3,4
!!!DATA 4,3,2,1 ! ※前の順列 ←←←←←
MAT READ A
MAT PRINT A;
FOR i=1 TO fact(N)
CALL NextPerm(A,N,rc)
PRINT i
IF rc=0 THEN
PRINT "ありません。"
STOP
END IF
MAT PRINT A;
NEXT i
END
EXTERNAL SUB NextPerm(A(),N, rc) !辞書式順序で次の順列を返す
LET i=N-1 !順列を右から左にみて、増加列から減少列に変わる位置iを探す
DO WHILE i>0 AND A(i)>=A(i+1) !0は番人
!!!DO WHILE i>0 AND A(i)<=A(i+1) !0は番人 ※前の順列 ←←←←←
LET i=i-1
LOOP
IF i=0 THEN !A(1)>A(2)>A(3)> … >A(N)なら 例. N=4、4,3,2,1
LET rc=0 !完了
EXIT SUB
END IF
LET j=N !その位置iより右で、A(i)以上で最小の数A(j)を探す
DO WHILE A(i)>=A(j)
!!!DO WHILE A(i)<=A(j) ! ※前の順列 ←←←←←
LET j=j-1
LOOP
LET t=A(i) !A(i)とA(j)を交換する
LET A(i)=A(j)
LET A(j)=t
LET i=i+1 !(i+1)からNまでの範囲を逆順にする
LET j=N
DO WHILE i<j
LET t=A(i) !swap it
LET A(i)=A(j)
LET A(j)=t
LET i=i+1
LET j=j-1
LOOP
LET rc=1 !未了
END SUB
!反転操作によるブロック移動
LET N=15 !枚数
DIM A(N) !カードの並び
PRINT "2分割の場合"
FOR i=1 TO N !整列
LET A(i)=i
NEXT i
MAT PRINT A;
LET p=5 !位置
CALL reverse(A,1,p-1) !前半部分のみ
MAT PRINT A;
CALL reverse(A,p,N) !後半部分のみ
MAT PRINT A;
CALL reverse(A,1,N) !全体で
MAT PRINT A;
PRINT
PRINT "3分割の場合"
FOR i=1 TO N !整列
LET A(i)=i
NEXT i
MAT PRINT A;
LET p=7 !位置
LET q=12
CALL reverse(A,1,p-1) !前半部分のみ
MAT PRINT A;
CALL reverse(A,p,q-1) !中央部分のみ
MAT PRINT A;
CALL reverse(A,q,N) !後半部分のみ
MAT PRINT A;
CALL reverse(A,1,N) !全体で
MAT PRINT A;
END
EXTERNAL SUB reverse(A(),L,R) !指定された範囲の並びを逆順にする
LET i=L !左端
LET j=R !右端
DO WHILE i<j !交換位置は半分まで ※全部すると元に戻る
LET t=A(i) !swap it
LET A(i)=A(j)
LET A(j)=t
LET i=i+1 !次へ
LET j=j-1
LOOP
END SUB
!Jn(z)=(1/π)*∫[0,π]{cos(n*θ-z*sinθ)}dθ 積分表示より、数値積分で求める
!(検算に使った)参考サイト http://keisan.casio.jp/
OPTION ARITHMETIC COMPLEX
LET j=SQR(-1) !虚数単位
DEF SIN(z)=(EXP(j*z)-EXP(-j*z))/(2*j) !三角関数
DEF COS(z)=(EXP(j*z)+EXP(-j*z))/2
FUNCTION complexbessel(n,z) !1種ベッセル関数 Jn(x+i*y)
LET div=1000 !分割数
LET u=0
LET h=PI/div
LET a=0
FOR i=1 TO div !数値積分の台形公式
LET u=u+( COS(n*a-z*SIN(a)) + COS(n*(a+h)-z*SIN(a+h)) )/2
LET a=h*i
NEXT i
LET complexbessel=h*u/PI
END FUNCTION
SET WINDOW -0.1*20,20, -1,1 !表示範囲
DRAW grid(20/4,1/5)
LET dx=0.2 !グラフの描画間隔
FOR n=0 TO 2
SET LINE COLOR n+2
SET TEXT COLOR n+2
PLOT TEXT,AT .13*20,1-.08*2-.04*2*n :"ベッセル関数1種 "& STR$(n)& "次"
FOR x=0 TO 20 STEP dx
LET y=Re( complexbessel(n,COMPLEX(x,0)) ) !実数
PLOT LINES: x,y;
IF FP(x)< dx THEN PRINT USING"##.## ###.######": x,y
NEXT x
PLOT LINES
PRINT
NEXT n
END
SUB window_i
CLEAR
LET h=4
LET l=-1.5
LET xr=4
SET WINDOW -.1*xr,xr, l,h
DRAW grid(xr/8,h/8)
ASK PIXEL SIZE (0,0; xr,0) j,i
LET dx=xr/j !pitch
END SUB
SUB window_j
CLEAR
LET h=1
LET l=-1
LET xr=20
SET WINDOW -.1*xr,xr, l,h
DRAW grid(xr/4,h/5)
ASK PIXEL SIZE (0,0; xr,0) j,i
LET dx=xr/j !pitch
END SUB
!-------
SUB G_besseli
FOR n=0 TO 2
SET LINE COLOR col(n)
SET TEXT COLOR col(n)
PLOT TEXT,AT .13*xr,h-.08*(h-l)-.04*(h-l)*n :"変形ベッセル関数1種 "& STR$(n)& "次"
FOR t=dx TO xr+dx STEP dx
LET x=t
LET y=besseli(n,x)
! LET x=COMPLEX(0,t)
! LET y=COMPLEX(0,1)^(-n)*besseli(n,x)
PLOT LINES: ABS(x),y; ! PEN-on
IF FP(t)< dx THEN PRINT x;y
NEXT t
PLOT LINES !PEN-off
PRINT
NEXT n
END SUB
SUB G_besselj
FOR n=0 TO 2
SET LINE COLOR col(n+3)
SET TEXT COLOR col(n+3)
PLOT TEXT,AT .13*xr,h-.08*(h-l)-.04*(h-l)*n :"ベッセル関数1種 "& STR$(n)& "次 "
FOR t=dx TO xr+dx STEP dx
! LET x=t
! LET y=besselj(n,x)
LET x=COMPLEX(0,t)
LET y=COMPLEX(0,1)^(-n)*besselj(n,x)
PLOT LINES: ABS(x),y; ! PEN-on
IF FP(t)< dx THEN PRINT x;y
NEXT t
PLOT LINES !PEN-off
PRINT
NEXT n
END SUB
!-------
FUNCTION besseli(n,x)
IF x=0 THEN LET x=1e-32 !0の保護( 場合により外す)
LET m=2*INT( (6+MAX(n,1.5*ABS(x))+9*1.5*ABS(x)/(1.5*ABS(x)+2))/2 )
LET w=0
FOR k=1 TO m
LET w=w+Tki(k,x)
NEXT k
LET besseli=EXP(x)*Tki(n,x)/(Tki(0,x)+2*w)
END FUNCTION
FUNCTION Tki(i,x)
LET t2=0
LET t1=1e-9
LET t0=2*(m+1)/x*t1+t2
FOR kp1=m TO i+1 STEP -1
LET t2=t1
LET t1=t0
LET t0=2*kp1/x*t1+t2
NEXT kp1
LET Tki=t0
END FUNCTION
!-------
FUNCTION besselj(n,x)
IF x=0 THEN LET x=1e-32 !0の保護( 場合により外す)
LET m=2*INT( (6+MAX(n,1.5*ABS(x))+9*1.5*ABS(x)/(1.5*ABS(x)+2))/2 )
LET w=0
FOR k=1 TO m/2
LET w=w+Tk(k*2,x)
NEXT k
LET besselj=Tk(n,x)/(Tk(0,x)+2*w)
END FUNCTION
FUNCTION Tk(i,x)
LET t2=0
LET t1=1e-9
LET t0=2*(m+1)/x*t1-t2
FOR kp1=m TO i+1 STEP -1
LET t2=t1
LET t1=t0
LET t0=2*kp1/x*t1-t2
NEXT kp1
LET Tk=t0
END FUNCTION
SET bitmap SIZE 640, 400
CLEAR
SET COLOR MIX(15) .4, .4, .4
SET COLOR MIX( 0) .4, .4, .4
SET AREA COLOR 1
DIM col(6),frq(6)
MAT READ col
DATA 4, 6, 2,
7, 3, 5 ! red yellow
blue magenta green cyan
MAT READ frq
DATA 10e3,40e3,60e3,100e3,1e6,10e6
!
LET a=0.5*1e-3 !m 導線半径.(1mmφ)
SET VIEWPORT 100/640,300/640, 100/640,300/640
CALL msub00
LET a=a/2 !m 導線半径.(.5mmφ)
SET VIEWPORT 350/640,550/640, 100/640,300/640
CALL msub00
!
SET VIEWPORT 0/640,640/640, 0/640,400/640
SET WINDOW 0,16, 10,0
SET TEXT COLOR 1
PLOT TEXT,AT 4,.5:"表皮効果によるエナメル線(銅)の電流密度分布"
PLOT TEXT,AT 4,1.3 ,USING"φ= %.##mm": a*4000
PLOT TEXT,AT 10.25,1.3 ,USING"φ= %.##mm": a*2000
PLOT TEXT,AT 3,2:"表皮 ← 中心 → 表皮"
PLOT TEXT,AT 9.25,2:"表皮 ← 中心 → 表皮"
PLOT AREA:.5,2.5;2,2.5;2,7.5;.5,7.5
FOR ch=1 TO 6
SET TEXT COLOR col(ch)
IF frq(ch)< 1e6 THEN LET w$=STR$(frq(ch)/1e3)& "KHz" ELSE LET w$=STR$(frq(ch)/1e6)& "MHz"
PLOT TEXT,AT .8, 3+.6*ch: w$
NEXT ch
!------
SUB msub00
SET WINDOW -a*1.01,a*1.01, -0.01,+1.01
PLOT AREA:-a*1.01,-0.01;a*1.01,-0.01;a*1.01,1.01;-a*1.01,1.01
DRAW axes0( a/5, 0.2)
ASK PIXEL SIZE(-a,0;a,0) j,i
LET dr=2*a/j
PRINT USING "φ= %.##mm": a*2000
FOR ch=1 TO 6
CALL skin
NEXT ch
END SUB
SUB skin
SET LINE COLOR col(ch)
LET k=SQR( COMPLEX(0,1)*2*PI*frq(ch)*u*g )
LET Iaa= ABS( besseli(0,k*a) ) !表面電流密度 A/m^2
!---
FOR r=dr TO a STEP dr
LET ra= ABS( besseli(0,k*r))/Iaa
IF r=dr THEN
IF frq(ch)< 1e6
THEN LET w$=STR$(frq(ch)/1e3)& "KHz" ELSE LET
w$=STR$(frq(ch)/1e6)& "MHz"
PRINT right$(" "& w$,6);" ";
PRINT USING$("###.########",ra*100);"%" !電流密度比(中心/表面)
ELSE
PLOT LINES:xb,yb; r,ra
PLOT LINES:-xb,yb;-r,ra
END IF
LET xb=r
LET yb=ra
NEXT r
END SUB
!------ 変形ベッセル関数1種0次
FUNCTION besseli(n,x)
LET m=2*INT( (6+MAX(n,1.5*ABS(x))+9*1.5*ABS(x)/(1.5*ABS(x)+2))/2)
LET w=0
FOR kk=1 TO m
LET w=w+Tki(kk,x)
NEXT kk
LET besseli=EXP(x)*Tki(n,x)/(Tki(0,x)+2*w)
END FUNCTION
FUNCTION Tki(i,x)
LET t2=0
LET t1=1e-9
LET t0=2*(m+1)/x*t1+t2
FOR kp1=m TO i+1 STEP -1
LET t2=t1
LET t1=t0
LET t0=2*kp1/x*t1+t2
NEXT kp1
LET Tki=t0
END FUNCTION
LET N=4 !N桁の階乗進数
DIM A(N) !各桁の値、順列
FOR i=0 TO FACT(N)-1 !場合の数
PRINT "i="; i !結果を表示する
CALL Num2Factoradic(i, A,N) !階乗進数へ
MAT PRINT A;
PRINT Factoradic2Num(A,N) !検算
CALL Num2PermFactorial(i,A,N) !順列へ
MAT PRINT A;
PRINT PermFactorial2Num(A,N) !検算
NEXT i
END
EXTERNAL FUNCTION Factoradic2Num(A(),N) !N桁の階乗進数に対して、非負整数を求める
FOR j=N TO 1 STEP -1
LET v=v*j+A(N-j+1) !階乗進数の各桁の値 A[1..N]=(N-1)! … 3! 2! 1! 0!
NEXT j
LET Factoradic2Num=v
END FUNCTION
EXTERNAL SUB Num2Factoradic(K, A(),N) !非負整数Kに対して、N桁の階乗進数を求める
LET v=K
FOR j=1 TO N
LET A(N-j+1)=MOD(v,j) !階乗進数の各桁の値 A[1..N]=(N-1)! … 3! 2! 1! 0!
LET v=INT(v/j)
NEXT j
END SUB
!n!の順列パターン ⇔ 0〜(n!-1)の番号
EXTERNAL FUNCTION PermFactorial2Num(A(),N) !順列パターンに番号を付ける ※辞書式順序
FOR j=1 TO N-1 !階乗進数の各桁の値+1 A[1..N]=(N-1)! … 3! 2! 1! 0!
FOR k=j+1 TO N
IF A(k)>=A(j) THEN LET A(k)=A(k)-1
NEXT k
NEXT j
LET v=0
FOR j=N TO 1 STEP -1 !非負の10進数整数へ
LET v=v*j+A(N-j+1)-1
NEXT j
LET PermFactorial2Num=v
END FUNCTION
EXTERNAL SUB Num2PermFactorial(h, A(),N) !番号から順列パターンを生成する ※辞書式順序
LET v=h !非負の10進数整数を階乗進数へ
FOR j=1 TO N
LET A(N-j+1)=MOD(v,j)+1 !階乗進数の各桁の値+1 A[1..N]=(N-1)! … 3! 2! 1! 0!
LET v=INT(v/j)
NEXT j
FOR j=N-1 TO 1 STEP -1 !順列パターンへ
FOR k=j+1 TO N
IF A(k)>=A(j) THEN LET A(k)=A(k)+1
NEXT k
NEXT j
END SUB
EXTERNAL FUNCTION Perm2Num(A(),N,R) !順列パターンに番号を付ける ※辞書式順序
FOR j=1 TO R-1 !(階乗)進数の各桁の値+1 A[1..R]=PERM(N-1,R-1) … PERM(N-j,R-j) … PERM(N-R,0)
FOR k=j+1 TO R
IF A(k)>=A(j) THEN LET A(k)=A(k)-1
NEXT k
NEXT j
LET v=0
FOR j=R TO 1 STEP -1 !非負の10進数整数へ
LET v=v*(N-R+j)+A(R-j+1)-1
NEXT j
LET Perm2Num=v
END FUNCTION
EXTERNAL SUB Num2Perm(h, A(),N,R) !番号から順列パターンを生成する ※辞書式順序
LET v=h !非負の10進数整数を(階乗)進数へ
FOR j=1 TO R
LET A(R-j+1)=MOD(v,N-R+j)+1 !(階乗)進数の各桁の値+1 A[1..R]=PERM(N-1,R-1) … PERM(N-j,R-j) … PERM(N-R,0)
LET v=INT(v/(N-R+j))
NEXT j
FOR j=R-1 TO 1 STEP -1 !順列パターンへ
FOR k=j+1 TO R
IF A(k)>=A(j) THEN LET A(k)=A(k)+1
NEXT k
NEXT j
END SUB
LET n1$="〇一二三四五六七八九" !漢数字
LET f1$="千百十 " !位
LET f2$="垓京兆億万 " !4桁ずつの位
LET n2$="〇壱弐参四伍六七八九" !大字
LET f3$="阡百拾 " !位
LET f4$="垓京兆億萬 " !4桁ずつの位
LET n3$="0123456789" !数字
DIM ff$(25)
FOR i=1 TO 25
READ IF MISSING THEN EXIT FOR : ff$(i)
NEXT i
!DATA 割,分,厘,毛,糸,忽,微,繊,沙,塵,埃,渺,漠,模糊,逡巡,須臾,瞬息,弾指,刹那,六徳,虚空,清浄,阿頼耶,阿摩羅,涅槃寂静 !割合表記
DATA 分,厘,毛,糸,忽,微,繊,沙,塵,埃,渺,漠,模糊,逡巡,須臾,瞬息,弾指,刹那,六徳,虚空,清浄,阿頼耶,阿摩羅,涅槃寂静 !本来表記
!"埃"以降は諸説あり
FUNCTION NumberString2$(x,p) !アラビア数字(1,2,3,…)を漢数字(一,二,三,…)に変換する
IF x<0 THEN
PRINT "非負ではありません。"; x
STOP
ELSE
LET w$=""
SELECT CASE p
CASE 1 !漢数字で表記する
LET a=INT(x) !!
IF a=0 THEN
LET w$="〇"
ELSE
LET i=LEN(f2$)
DO UNTIL a=0 !上位の数字がなくなるまで
LET aa=MOD(a,10000) !「…兆億万 」の4桁ずつ
IF aa<>0 THEN
LET ww$=f2$(i:i)
IF
ww$<>" " THEN LET w$=ww$&w$
LET k=LEN(f1$)
DO
UNTIL aa=0 !各「千百十 」の位
LET ww$=f1$(k:k)
IF ww$=" " THEN LET ww$=""
LET t=MOD(aa,10) !一の位から
IF t=0 THEN !ゼロ・サプレス
ELSEIF k<LEN(f1$) AND t=1 THEN !1・サプレス
LET
w$=ww$&w$
ELSE
LET
w$=n1$(t+1:t+1)&ww$&w$
END IF
LET aa=INT(aa/10) !次へ
LET k=k-1
LOOP
END IF
LET a=INT(a/10000) !次へ
LET i=i-1
LOOP
END IF
CASE 2 !大字の漢数字で表記する
LET a=INT(x) !!
IF a=0 THEN
LET w$="〇"
ELSE
LET i=LEN(f4$)
DO UNTIL a=0 !上位の数字がなくなるまで
LET aa=MOD(a,10000) !「…兆億万 」の4桁ずつ
IF aa<>0 THEN
LET ww$=f4$(i:i)
IF
ww$<>" " THEN LET w$=ww$&w$
LET k=LEN(f3$)
DO
UNTIL aa=0 !各「千百十 」の位
LET ww$=f3$(k:k)
IF ww$=" " THEN LET ww$=""
LET t=MOD(aa,10) !一の位から
IF t=0 THEN !ゼロ・サプレス
!!!ELSEIF k<LEN(f3$) AND t=1 THEN !1・サプレス
!!! LET w$=ww$&w$
ELSE
LET
w$=n2$(t+1:t+1)&ww$&w$
END IF
LET aa=INT(aa/10) !次へ
LET k=k-1
LOOP
END IF
LET a=INT(a/10000) !次へ
LET i=i-1
LOOP
END IF
CASE 3 !数値をそのまま漢数字で表記する
LET a=INT(x) !!
IF a=0 THEN
LET w$="〇" !!
ELSE
DO UNTIL a=0 !上位の桁がなくなるまで
LET t=MOD(a,10)+1 !一の位から
LET w$=n1$(t:t)&w$
LET a=INT(a/10) !次へ
LOOP
END IF
CASE 4 !十,百,千,万などを漢数字で表記する
LET a=INT(x) !!
IF a=0 THEN
LET w$="0" !!
ELSE
LET i=LEN(f2$)
DO UNTIL a=0 !上位の数字がなくなるまで
LET aa=MOD(a,10000) !「…兆億万 」の4桁ずつ
IF aa<>0 THEN
LET ww$=f2$(i:i)
IF
ww$<>" " THEN LET w$=ww$&w$
LET k=LEN(f1$)
DO
UNTIL aa=0 !各「千百十 」の位
LET ww$=f1$(k:k)
IF ww$=" " THEN LET ww$=""
LET t=MOD(aa,10) !一の位から
IF t=0 THEN !ゼロ・サプレス
ELSEIF k<LEN(f1$) AND t=1 THEN !1・サプレス
LET
w$=ww$&w$
ELSE
LET
w$=n3$(t+1:t+1)&ww$&w$
END IF
LET aa=INT(aa/10) !次へ
LET k=k-1
LOOP
END IF
LET a=INT(a/10000) !次へ
LET i=i-1
LOOP
END IF
CASE 5 !! 兆,億,万などを漢数字で表記する
LET a=INT(x)
IF a=0 THEN
LET w$="0"&w$
ELSE
LET i=LEN(f2$)
DO UNTIL a=0 !上位の数字がなくなるまで
LET aa=MOD(a,10000) !「…兆億万 」の4桁ずつ
IF aa<>0 THEN
LET ww$=f2$(i:i)
IF
ww$<>" " THEN LET w$=ww$&w$
DO
UNTIL aa=0 !各「千百十 」の位
LET t=MOD(aa,10) !一の位から
LET w$=n3$(t+1:t+1)&w$
LET aa=INT(aa/10) !次へ
LOOP
END IF
LET a=INT(a/10000) !次へ
LET i=i-1
LOOP
END IF !!
CASE ELSE
END SELECT
IF x<>INT(x) THEN !!
IF INT(x)=0 THEN
LET w$=""
ELSEIF p=1 OR p=2 OR p=4 THEN
LET w$=w$&"・"
END IF
LET w$=w$&NumberString3$(FP(x),p) ! 小数部変換
END IF !!
LET NumberString2$=w$ !結果を返す
END IF
END FUNCTION
!続く
!続き
FUNCTION NumberString3$(x,p) !アラビア数字小数部(.123…)を漢数字(一分二厘三毛…)に変換する
IF x<=0 OR x>=1 THEN
PRINT "正の小数(0<x<1)ではありません。"; x
STOP
END IF
LET b=x
LET ww$=""
LET k=1
SELECT CASE p
CASE 1 !漢数字で表記する(一分二厘三毛)
DO UNTIL b=0 !小数がなくなるまで
LET t=INT(10*b)
WHEN EXCEPTION IN
LET ff2$=ff$(k) ! 配列添字オーバーで例外発生
IF t<>0 THEN LET ww$=ww$&n1$(t+1:t+1)&ff2$
USE
LET ww$=ww$&n1$(t+1:t+1) ! t=0を表記
END WHEN
LET b=10*b-t !次へ
LET k=k+1
LOOP
CASE 2 !大字の漢数字で表記する(壱分弐厘参毛)
DO UNTIL b=0 !小数がなくなるまで
LET t=INT(10*b)
WHEN EXCEPTION IN
LET ff2$=ff$(k)
IF
t<>0 THEN LET ww$=ww$&n2$(t+1:t+1)&ff$(k)
USE
LET ww$=ww$&n2$(t+1:t+1)
END WHEN
LET b=10*b-t !次へ
LET k=k+1
LOOP
CASE 3 !数値をそのまま漢数字で表記する(・一二三)
LET ww$="・" ! 中黒
DO UNTIL b=0 !小数がなくなるまで
LET t=INT(10*b)
LET ww$=ww$&n1$(t+1:t+1)
LET b=10*b-t !次へ
LOOP
CASE 4 !分,厘,毛,糸などを漢数字で表記する(1分2厘3毛)
DO UNTIL b=0 !小数がなくなるまで
LET t=INT(10*b)
WHEN EXCEPTION IN
LET ff2$=ff$(k)
IF
t<>0 THEN LET ww$=ww$&n3$(t+1:t+1)&ff$(k)
USE
LET ww$=ww$&n3$(t+1:t+1)
END WHEN
LET b=10*b-t !次へ
LET k=k+1
LOOP
CASE 5 !全角数字で表記する(.123)
LET ww$="." ! 全角ピリオド
DO UNTIL b=0 !小数がなくなるまで
LET t=INT(10*b)
LET ww$=ww$&n3$(t+1:t+1)
LET b=10*b-t !次へ
LOOP
CASE ELSE
END SELECT
LET NumberString3$=ww$ !結果を返す
END FUNCTION
PRINT NumberString2$(1234567890.1204,1) !十二億三千四百五十六万七千八百九十・一分二厘四糸
PRINT NumberString2$(1234567890.1204,2) !壱拾弐億参阡四百伍拾六)萬七阡八百九拾・壱分弐厘四糸
PRINT NumberString2$(1234567890.1204,3) !一二三四五六七八九〇・一二〇四
PRINT NumberString2$(1234567890.1204,4) !十2億3千4百5十6万7千8百9十・1分2厘4糸
PRINT NumberString2$(1234567890.1204,5) !12億3456万7890.1204
PRINT
DIM x(4)
FOR p=1 TO 5
PRINT NumberString2$(PI,p)
NEXT p
PRINT
LET x(1)=5000021007
LET x(2)=.023006
LET x(3)=48130000000
LET x(4)=7.31650080029041875E23 !※1000桁モード、有理数モード
FOR p=1 TO 5
FOR ii=1 TO 4
PRINT NumberString2$(x(ii),p),
NEXT ii
PRINT
NEXT p
END
!漢数字を数値に変換する関数 String_to_Num(a$)
10 DIM nk$(4,0 TO 9),f1$(3),f2$(5),ff$(25)
20 DATA 0,1,2,3,4,5,6,7,8,9 ! nk$
30 DATA 〇,一,二,三,四,五,六,七,八,九 ! nk$
40 DATA 零,壱,弐,参,肆,伍,陸,漆,捌,玖 ! nk$
50 DATA ○,壹,貳,參,4,5,6,質,8,9 ! nk$
60 DATA 千,百,十 ! f1$
70 DATA 垓,京,兆,億,万 ! f2$(5)
80 !DATA 割,分,厘,毛,糸,忽,微,繊,沙,塵,埃,渺,漠,模糊,逡巡,須臾,瞬息,弾指,刹那,六徳,虚空,清浄,阿頼耶,阿摩羅,涅槃寂静 !割合表記
90 DATA 分,厘,毛,糸,忽,微,繊,沙,塵,埃,渺,漠,模糊,逡巡,須臾,瞬息,弾指,刹那,六徳,虚空,清浄,阿頼耶,阿摩羅,涅槃寂静 !本来表記
! "埃"以降は諸説あり
100 MAT READ nk$,f1$,f2$
110 FOR i=1 TO 25
120 READ IF MISSING THEN EXIT FOR : ff$(i)
130 NEXT i
170 FUNCTION String_to_Num(w$)
180 DO
190 LET i=MAX(POS(w$," "),POS(w$," "))
200 LET w$(i:i)=""
210 LOOP UNTIL i=0
220 FOR i=1 TO LEN(w$)
230 FOR p=1 TO 4 ! 全角数字/漢数字を半角算用数字に
240 FOR j=0 TO 9
250 IF w$(i:i)=nk$(p,j) THEN LET w$(i:i)=STR$(j)
260 NEXT j
270 NEXT p
280 IF w$(i:i)="阡" OR w$(i:i)="仟" THEN LET w$(i:i)="千"
290 IF w$(i:i)="陌" OR w$(i:i)="佰" THEN LET w$(i:i)="百"
300 IF w$(i:i)="拾" THEN LET w$(i:i)="十"
310 NEXT i
320 LET i=POS(w$,"萬")
330 IF i>0 THEN LET w$(i:i)="万"
340 LET i=POS(w$,"6徳")
350 IF i>0 THEN LET w$(i:i+1)="六徳"
360 LET pt=POS(w$,".")+POS(w$,".")+POS(w$,"・")
370 IF pt>0 THEN
380 LET w$(pt:pt)="."
390 LET len_int=pt-1 ! 整数部文字数
400 ELSE
410 LET len_int=LEN(w$)
420 END IF
! print w$
!
430 WHEN EXCEPTION IN
440 LET num=VAL(w$)
450 LET String_to_Num=num ! "一二三四五・六七"(数字のみ)
460 EXIT FUNCTION
470 USE
480 END WHEN
!
490 LET num=i_val(w$) ! 整数部変換
!
500 IF pt>0 THEN
510 LET f$=w$(pt:LEN(w$))
520 WHEN EXCEPTION IN
530 LET num=num+VAL(f$)
540 LET String_to_Num=num ! "12万3456.78"(小数部が数字のみ)
550 USE
560 LET String_to_Num=num+f_val(f$(2:LEN(f$))) ! "十二・三分四厘"(整数小数あり)
570 END WHEN
580 ELSEIF num=0 AND LEN(w$)>=2 THEN
590 LET String_to_Num=f_val(w$) ! "一分二厘三毛四糸"(小数部のみ)
600 ELSE
610 LET String_to_Num=num ! "百二十三"(整数部のみ)
620 END IF
630 END FUNCTION
!
640 FUNCTION i_val(w$) ! 整数部変換
650 LET num=0
660 LET k0=1
670 FOR i=1 TO SIZE(f2$)
680 LET k2=POS(w$,f2$(i),k0+1) ! 垓,京,兆,億,万
690 IF k2>0 THEN
700 LET num=num+val1000(w$(k0:k2-1))*10000^(SIZE(f2$)-i+1) ![千百十一]の4桁
710 LET k0=k2+1
720 END IF
730 NEXT i
740 IF k0<=len_int THEN ! 最下位4桁
750 LET num=num+val1000(w$(k0:len_int))
760 END IF
770 LET i_val=num
780 END FUNCTION
!
790 FUNCTION val1000(aa$) ! [千百十一]の4桁変換
800 WHEN EXCEPTION IN
810 LET aa=VAL(aa$)
820 LET val1000=aa
830 EXIT FUNCTION
840 USE
850 END WHEN
860 LET aa=0
870 LET kk=1
880 FOR j=1 TO 3
890 LET k1=POS(aa$,f1$(j),kk) ! 千,百,十
900 IF k1>0 THEN
910 WHEN EXCEPTION IN
920 LET aa=aa+VAL(aa$(k1-1:k1-1))*10^(4-j)
930 USE
940 LET aa=aa+10^(4-j) ! 係数"1"の省略時(3千百4十5など)
950 END WHEN
960 LET kk=k1+1
970 END IF
980 NEXT j
990 IF kk=LEN(aa$) THEN LET aa=aa+VAL(aa$(kk:kk)) ! 一
1000 LET val1000=aa
1010 END FUNCTION
!
1020 FUNCTION f_val(f$) ! 小数部変換
1030 LET frac=0
1040 LET k0=1
1050 FOR i=1 TO SIZE(ff$)
1060 IF ff$(i)<>"" THEN
1070 LET fd=POS(f$,ff$(i),k0+1)
1080 IF fd>0 THEN
1090 LET frac=frac+VAL(f$(fd-1:fd-1))*10^(-i)
1100 LET k0=fd+LEN(ff$(i))
1110 LET k3=i
1120 END IF
1130 END IF
1140 NEXT i
1150 WHEN EXCEPTION IN
1160 IF k0<=LEN(f$) THEN
1170 LET frac=frac+VAL(f$(k0:LEN(f$)))*10^(-(k3+LEN(f$)-k0+1))
1180 END IF
1190 USE
1200 END WHEN
1210 LET f_val=frac
1220 END FUNCTION
!
1230 END
220 point -10:word -40:M=1850:dim C(M):C(0)=1:S=1/2+14#i
250 for K=1 to M:for J=K to 1 step -1:C(J)=(C(J)+C(J-1))/2:next:next
300 ' find zeta zero
330 repeat
350 Z=fnZeta(S):H=Z/S:W=fnZeta(S+H):S+=H/(1-W/Z)
360 print using(8,20),S
380 until abs(Z)<1/10^18
390 end
800 ' zeta function
810 fnZeta(X)
820 local J,U
830 for J=1 to M:U+=(-1)^(J-1)*C(J)/J^X:next:U/=1-2^(1-X)
880 return(U)
OPTION ARITHMETIC COMPLEX
OPTION BASE 0
!
!point -10 !変数の小数部 10*4.8桁 設定不可。
!
!word -40 !変数の長さ 40*4.8桁 設定不可。
LET
M=1850
!※短くても内部計算は常に2600桁。
DIM C(M)
LET C(0)=1
LET S=COMPLEX(1/2,14) !S=1/2+14#i
FOR K=1 TO M
FOR J=K TO 1 STEP -1
LET C(J)=(C(J)+C(J-1))/2
NEXT J
NEXT K
!' find zeta zero
DO !repeat
LET
Z=Zeta(S) !Z=fnZeta(S)
LET H=Z/S
LET
W=Zeta(S+H) !W=fnZeta(S+H)
LET S=S+H/(1-W/Z) !S+=H/(1-W/Z)
PRINT
S !print
using(8,20),S
! PRINT USING "########.#################### ########.####################":re(S),im(S);
! PRINT "#i"
LOOP UNTIL ABS(Z)< 1e-12 ! 1e-14 !until abs(Z)< 1/10^18 !十進BASICで ^18は無理。
STOP !END
!' zeta function
FUNCTION
Zeta(X) !fnZeta(X)
※'fn'は、ユーザー定義関数 接頭語
local J,U
FOR J=1 TO M
LET U=U+(-1)^(J-1)*C(J)/J^X !U+=(-1)^(J-1)*C(J)/J^X
NEXT J
LET U=U/(1-2^(1-X)) !U/=1-2^(1-X)
LET
Zeta=U
!return(U)
END FUNCTION
OPTION ARITHMETIC DECIMAL_HIGH
220 ! point -10:word -40
DECLARE EXTERNAL FUNCTION LOG,EXP
DECLARE FUNCTION SIN,COS
PUBLIC NUMERIC prec
print time$
LET t0=time
LET prec=50 ! 精度
LET M=1850
DIM C(0 TO M),L(M),inv_fac(0 TO prec+1),S(2),Z(2),H(2),W(2),SH(2)
LET C(0)=1
LET S(1)=1/2
LET S(2)=14
250 for K=1 to M
LET L(K)=LOG(K)
for J=K to 1 step -1
LET C(J)=(C(J)+C(J-1))/2 ! C(K)=2^(-K)?
next J
next K
LET inv_fac(0)=1 ! 階乗の逆数
FOR i=1 TO prec+1
LET inv_fac(i)=inv_fac(i-1)/i
NEXT i
300 !' find zeta zero
330 DO ! repeat
350 CALL fnZeta(S,Z)
LET H(1)=(Z(1)*S(1)+Z(2)*S(2))/(S(1)^2+S(2)^2) ! H=Z/S
LET H(2)=(Z(2)*S(1)-Z(1)*S(2))/(S(1)^2+S(2)^2)
MAT SH=S+H
CALL fnZeta(SH,W) ! W=fnZeta(S+H)
LET SH(1)=1-(W(1)*Z(1)+W(2)*Z(2))/(Z(1)^2+Z(2)^2)
LET SH(2)=-(W(2)*Z(1)-W(1)*Z(2))/(Z(1)^2+Z(2)^2)
LET S(1)=S(1)+(H(1)*SH(1)+H(2)*SH(2))/(SH(1)^2+SH(2)^2) ! S+=H/(1-W/Z)
LET S(2)=S(2)+(H(2)*SH(1)-H(1)*SH(2))/(SH(1)^2+SH(2)^2)
360 print using
"-"&REPEAT$("#",7)&"."&REPEAT$("#",20)&"
-"&REPEAT$("#",7)&"."&REPEAT$("#",20):S(1),S(2)
380 LOOP until SQR(Z(1)^2+Z(2)^2)<1/10^18
print int(time-t0);"秒"
390 ! end
800 !' zeta function
810 SUB fnZeta(X(),U())
820 local J
MAT U=ZER
830 for J=1 to M
LET p1=EXP(X(1)*L(J))*COS(X(2)*L(J))
LET p2=EXP(X(1)*L(J))*SIN(X(2)*L(J))
LET pp=1/(p1^2+p2^2)
LET U(1)=U(1)+(-1)^(J-1)*C(J)*p1*pp ! U+=(-1)^(J-1)*C(J)/J^X
LET U(2)=U(2)-(-1)^(J-1)*C(J)*p2*pp
next J
LET p1=1-EXP((1-X(1))*L(2))*COS(-X(2)*L(2))
LET p2=-EXP((1-X(1))*L(2))*COS(-X(2)*L(2))
LET pp=1/(p1^2+p2^2)
LET u1=(U(1)*p1+U(2)*p2)*pp
LET U(2)=(U(2)*p1-U(1)*p2)*pp ! U/=1-2^(1-X)
LET U(1)=u1
880 END SUB ! return(U)
!
FUNCTION SIN(x)
LET x=MOD(x,2*PI)
LET sum=0
FOR i=0 TO prec/2
LET sum=sum+(-1)^i*x^(2*i+1)*inv_fac(2*i+1)
NEXT i
LET SIN=sum
END FUNCTION
FUNCTION COS(x)
LET x=MOD(x,2*PI)
LET sum=0
FOR i=0 TO prec/2
LET sum=sum+(-1)^i*x^(2*i)*inv_fac(2*i)
NEXT i
LET COS=sum
END FUNCTION
END
!
! 1000桁モードで利用する対数関数(十進BASIC添付"\BASICw32\Library\log.LIB"参照)
EXTERNAL FUNCTION LOG(x)
OPTION ARITHMETIC DECIMAL_HIGH
IF x<=0 THEN
CAUSE EXCEPTION 3004
ELSEIF x<1 THEN
LET log=-log(1/x)
ELSEIF x>3 THEN
LET log=2*log(SQR(x))
ELSE ! 1<=x<=3
LET h=(x-1)/(x+1) ! 0<=h<=0.5
LET t=0
LET n=1
LET k=h
LET h2=H^2
DO
LET t=t+k/n
LET n=n+2
LET k=k*h2
LOOP UNTIL k<=eps(0)*10^(1000-prec) ! 精度prec
LET log=2*t
END IF
END FUNCTION
!
! 1000桁モードで利用する指数関数(十進BASIC添付"\BASICw32\Library\exp.LIB"参照)
EXTERNAL FUNCTION EXP(x)
OPTION ARITHMETIC DECIMAL_HIGH
FUNCTION s(y,n)
LET t=y*x/n
IF ABS(t)<=EPS(0)*10^(1000-prec) THEN ! 精度prec
LET s=y+t
ELSE
LET s=y+s(t,n+1)
END IF
END FUNCTION
LET EXP=s(1,1)
END FUNCTION
!リーマンのゼータ関数
!ζ(s)=1/(1-2^(1-s))*��[m=0,∞]{2^(-(m+1))*��[j=0,m]{(-1)^j*comb(m,j)*(j+1)^(-s)}}
LET t0=TIME
LET M=50 !1850
DIM C(0 TO M) !��2^(-(M+1))*��comb(M,J)
LET C(0)=1
FOR K=1 TO M !パスカルの三角形のM段より、二項係数comb(m,j)を求める
FOR J=K TO 1 STEP -1
LET C(J)=(C(J)+C(J-1))/2 !※2^(-(m+1))も加味する
NEXT J
NEXT K
FUNCTION fnZeta(S) !リーマンのゼータ関数
local J,U
LET U=0
FOR J=0 TO M
LET U=U+(-1)^J*C(J)/(J+1)^S
NEXT J
LET U=U/(1-2^(1-S))
LET fnZeta=U
END FUNCTION
PRINT C(M) !debug
PRINT fnZeta(2) - PI*PI/6
PRINT "計算時間=";TIME-t0
END
LET t1$="<H2><A NAME=""CID" ! ID No.
LET t1=LEN(t1$)
LET t2$=""" HREF=""http://6317.teacup.com/basic/bbs/" ! ID No.
LET t2=LEN(t2$)
LET t3$=""" CLASS=""Kiji_Title"">" ! タイトル
LET t3=LEN(t3$)
LET t4$="</A></H2>"
LET t4=LEN(t4$)
!
LET p1$=" 投稿者:<SPAN CLASS=""Kiji_Author"">" ! 投稿者
LET p1=LEN(p1$)
LET p2$="</SPAN>"
LET p2=LEN(p2$)
LET p3$="<A HREF=" ! mailto
LET p3=LEN(p3$)
LET p4$=""">"
LET p4=LEN(p4$)
LET p5$="</A>"
LET p5=LEN(p4$)
!
LET d1$=" 投稿日:" ! 投稿日時
LET d1=LEN(d1$)
LET d2$="日(" ! 曜日
LET d2=LEN(d2$)
!
LET l1$="> <A HREF=""http://6317.teacup.com/basic/bbs/" ! 元記事 No.
LET l1=LEN(l1$)
LET l2$=">No." ! 元記事 No.
LET l2=LEN(l2$)
LET l3$="[元記事へ]</A><BR><BR>"
LET l3=LEN(l3$)
!
LET finput$="source.txt"
LET foutput$="boardlist.txt"
OPEN #1 : NAME finput$ ,ACCESS INPUT
!
DIM c$(1000)
LET k=0
DO
LINE INPUT #1 , IF MISSING THEN EXIT DO : a$
IF a$(1:l1)=l1$ THEN ! 元記事あり
LET ps=POS(a$,l2$,l1+1)
LET ps2=POS(a$,l3$,ps+l2)
LET s$=s$&" "&a$(ps:ps2-1)
ELSEIF a$(1:t1)=t1$ THEN
IF s$<>"" THEN
LET k=k+1
LET c$(k)=s$&"</SMALL>"
END IF
CALL title
END IF
LOOP
IF s$<>"" THEN
LET k=k+1
LET c$(k)=s$&"</SMALL>"
END IF
CLOSE #1
!
OPEN #2 : NAME foutput$ ,ACCESS OUTPUT
SET #2 : POINTER END
FOR i=k TO 1 STEP -1
PRINT #2 : c$(i)
NEXT i
CLOSE #2
!
SUB title
LET s$="<A HREF=""http://6317.teacup.com/basic/bbs/"
LET id$=a$(t1+1:POS(a$,"""",t1+1)-1)
LET s$=id$&" "&s$&id$&"""><B><BIG>"
LET ps=POS(a$,t3$,t1+2)
LET ps2=POS(a$,t4$,ps+t3)
LET
s$=s$&a$(ps+t3:ps2-1)&"</BIG></B></A>
投稿者:<FONT COLOR=""#555555""><STRONG>"
LINE INPUT #1 : a$
IF a$(1:p1)=p1$ THEN
IF a$(p1+1:p1+p3)=p3$ THEN
LET
s$=s$&a$(POS(a$,p4$,p1+p3+1)+p4:POS(a$,p5$,p1+p3+3)-1)&"</STRONG></FONT><SMALL>"
ELSE
LET
s$=s$&a$(p1+1:POS(a$,p2$,p1+1)-1)&"</STRONG></FONT><SMALL>"
END IF
END IF
LINE INPUT #1 : a$
LINE INPUT #1 : a$
IF a$(1:d1)=d1$ THEN
LET s$=s$&" "&a$(d1+1:POS(a$,d2$,d1+2))
END IF
END SUB
END
FOR i=10 TO 99 !2桁の数を念じる
LET a=INT(i/10) !十の位と一の位の2つの数字を足す
LET b=MOD(i,10) !2桁の数字から足した答えを引く
LET s=i-(a+b) !答え s=(10*a+b)-(a+b)=9*a ∴9の倍数
PRINT i;s !9の倍数は同じマークにして、常にこのマークを表示すればよい。
!ただ、多少はずれるように異なるマークも表示する
NEXT i
END
RANDOMIZE
SET bitmap SIZE 501,501
SET WINDOW -0.5,10.5,10,-1
LET z$="c" !9の倍数は同じマーク
!!!SET TEXT font "MS明朝",12
FOR y=0 TO 9 !数字
FOR x=0 TO 9
PLOT TEXT ,AT x,y: STR$(10*y+x)
NEXT x
NEXT y
SET TEXT font "Wingdings",18 !※大きさは調整が必要である
FOR y=0 TO 9 !占星術のシンボル
FOR x=0 TO 9
IF MOD(10*y+x,9)=0 THEN !9の倍数なら
PLOT TEXT ,AT x+0.3,y+0.3: z$
ELSE
PLOT TEXT ,AT x+0.3,y+0.3: CHR$(INT(RND*40)+ORD("T")) !T〜z
END IF
NEXT x
NEXT y
INPUT PROMPT "何か文字を入力してください。":t$ !ダミー入力!!!
SET TEXT font "Wingdings",256 !※大きさは調整が必要である
SET TEXT JUSTIFY "center","half"
PLOT TEXT ,AT 5,4.5: z$
END
!複素数の計算
LET t0=TIME
!リーマンのゼータ関数
! ζ(s)=1/(1-2^(1-s))*��[m=0,∞]{2^(-(m+1))*��[j=0,m]{(-1)^j*comb(m,j)*(j+1)^(-s)}}
LET M=100 !精度20桁程度 ※精度1000桁程度は、3000
DIM C(0 TO M) !��2^(-(M+1))*��comb(M,J)
LET C(0)=1
FOR K=1 TO M !パスカルの三角形のM段より、二項係数comb(m,j)を求める
FOR J=K TO 1 STEP -1
LET C(J)=(C(J)+C(J-1))/2 !※2^(-(m+1))も加味する
NEXT J
NEXT K
PRINT C(M) !debug
SUB fnZeta(ReS,ImS, ReZ,ImZ) !リーマンのゼータ関数
local J
local ReU,ImU,ReT1,ImT1,ReT2,ImT2
LET ReU=0 !LET U=0
LET ImU=0
FOR J=M TO 0 STEP -1
CALL CompPow(J+1,0, ReS,ImS, ReT1,ImT1) !LET U=U+(-1)^J*C(J)/(J+1)^S
CALL CompDiv((-1)^J*C(J),0, ReT1,ImT1, ReT2,ImT2)
CALL CompAdd(ReU,ImU, ReT2,ImT2, ReU,ImU)
NEXT J
CALL CompPow(2,0, 1-ReS,-ImS, ReT1,ImT1) !LET fnZeta=U/(1-2^(1-S))
CALL CompDiv(ReU,ImU, 1-ReT1,ImT1, ReZ,ImZ)
END SUB
!ゼータ関数の零点の計算(Riemann zeta zeros)
LET ReS=1/2 !非自明な零点 1/2+14*i
LET ImS=14 !1/2+t*i t=14, 21, 25, 30, 33, 38, 41, 43, 48, 50, … 付近
!ニュートン法で零点を求める
! sn+1 = sn-ζ(sn)/ζ'(sn)、ζ'(sn)≒(ζ(sn+h)-ζ(sn))/h hは微小な値より
! sn+1 = sn-ζ(sn)*h/(ζ(sn+h)-ζ(sn)) = sn+h/(1-ζ(sn+h)/ζ(sn)) となる。
! h=ζ(sn)/sn として、収束の判定にはζ(s)の絶対値を使用する。
DO
CALL fnZeta(ReS,ImS, ReZ,ImZ) !LET Z=fnZeta(S)
CALL CompDiv(ReZ,ImZ,ReS,ImS, ReH,ImH) !LET H=Z/S
CALL fnZeta(ReS+ReH,ImS+ImH, ReW,ImW) !LET W=fnZeta(S+H)
CALL CompDiv(ReW,ImW, ReZ,ImZ, ReT1,ImT1) !LET S=S+H/(1-W/Z)
CALL CompDiv(ReH,ImH, 1-ReT1,-ImT1, ReT2,ImT2)
CALL CompAdd(ReS,ImS, ReT2,ImT2, ReS,ImS)
PRINT USING "####.#################### ####.####################": ReS,ImS !PRINT S
LOOP UNTIL CompABS(ReZ,ImZ)<1/10^18 !LOOP UNTIL ABS(Z)<1/10^18
!収束するまで ※精度は調整が必要である。10進モード、2進モードでは1/10^8程度
PRINT "計算時間=";TIME-t0
END
!複素数の計算
EXTERNAL FUNCTION CompRe(x,y) !実部 (x+y*i)、x,yは実数、iは虚数単位
LET CompRe=x
END FUNCTION
EXTERNAL FUNCTION CompIm(x,y) !虚部 Im(x+y*i)
LET CompIm=y
END FUNCTION
EXTERNAL SUB CompConj(x1,y1, x,y) !共役複素数
LET xx=x1
LET yy=-y1
LET x=xx
LET y=yy
END SUB
EXTERNAL FUNCTION CompABS(x,y) !絶対値 |x+y*i|
!a'=MAX(ABS(a),ABS(b))、b'=MIN(ABS(a),ABS(b))として、SQR(a*a+b*b)=a'*SQR(1+(b'/a')^2)を求める。
IF x=0 THEN
LET r=ABS(y)
ELSEIF y=0 THEN
LET r=ABS(x)
ELSEIF ABS(y)>ABS(x) THEN
LET t=x/y
LET r=ABS(y)*SQR(1+t*t)
ELSE
LET t=y/x
LET r=ABS(x)*SQR(1+t*t)
END IF
LET CompABS=r
END FUNCTION
EXTERNAL FUNCTION CompARG(x,y) !偏角θ (-π,π]
IF x>0 THEN !第1象限、第4象限
LET r=ATN2(y/x)
ELSE
IF x<0 THEN
IF y>=0 THEN !第2象限
LET r=ATN2(y/x)+PI
ELSE !第3象限
LET r=ATN2(y/x)-PI
END IF
ELSE !x=0
IF y>0 THEN !∞
LET r=PI/2
ELSE
IF y<0 THEN !-∞
LET r=-PI/2
ELSE !y=0
PRINT "ARG関数は不定です。"
STOP
END IF
END IF
END IF
END IF
LET CompARG=r
END FUNCTION
!演算関連 べき乗
EXTERNAL SUB CompPow(x1,y1, x2,y2, x,y) !べき乗 (x1+y1*i) ^ (x2+y2*i) → x+y*i
CALL CompLOG(x1,y1, s,t) !z1^z2=exp(log(z1)*z2)より
CALL CompMul(s,t, x2,y2, a,b)
CALL CompEXP(a,b, x,y)
END SUB
!演算関連 四則演算、関数など
EXTERNAL SUB CompAdd(x1,y1, x2,y2, x,y) !加算 (x1+y1*i) + (x2+y2*i) → x+y*i
LET xx=x1+x2 !実部
LET yy=y1+y2 !虚部
LET x=xx
LET y=yy
END SUB
EXTERNAL SUB CompSub(x1,y1, x2,y2, x,y) !減算 (x1+y1*i) - (x2+y2*i) → x+y*i
LET xx=x1-x2
LET yy=y1-y2
LET x=xx
LET y=yy
END SUB
EXTERNAL SUB CompMul(x1,y1, x2,y2, x,y) !乗算 (x1+y1*i) * (x2+y2*i) → x+y*i
LET xx=x1*x2-y1*y2 !丸め誤差対策
LET yy=x1*y2+y1*x2
LET x=xx
LET y=yy
END SUB
EXTERNAL SUB CompDiv(x1,y1, x2,y2, x,y) !除算 (x1+y1*i) / (x2+y2*i) → x+y*i
IF x2=0 AND y2=0 THEN
PRINT "0では割れません。"
STOP
END IF
IF ABS(x2)>=ABS(y2) THEN !上位桁あふれ対策
LET w=y2/x2
LET tt=x2+y2*w
LET xx=(x1+y1*w)/tt
LET yy=(y1-x1*w)/tt
ELSE
LET w=x2/y2
LET tt=x2*w+y2
LET xx=(x1*w+y1)/tt
LET yy=(y1*w-x1)/tt
END IF
LET x=xx
LET y=yy
END SUB
EXTERNAL SUB CompSQR(x1,y1, x,y) !平方根
LET SQRT05=SQR(1/2) !0.707106781186547524
LET r=CompABS(x1,y1) !r=SQR(x1*x1+y1*y1)
LET w=SQR(r+ABS(x1))
IF x1>=0 THEN
LET x=SQRT05*w
LET y=SQRT05*y1/w
ELSE
LET x=SQRT05*ABS(y1)/w
IF y1>=0 THEN LET y=SQRT05*w ELSE LET y=-SQRT05*w
END IF
END SUB
EXTERNAL SUB CompEXP(x1,y1, x,y) !指数関数
DECLARE EXTERNAL FUNCTION EXP,SIN,COS !関数のオーバーロード
LET t=EXP(x1) !EXP(x+i*y)=EXP(x)*EXP(i*y)=EXP(x)*(COS(y)+i*SIN(y))
LET xx=t*COS(y1)
LET yy=t*SIN(y1)
LET x=xx
LET y=yy
END SUB
EXTERNAL SUB CompLOG(x1,y1, x,y) !対数関数
DECLARE EXTERNAL FUNCTION LOG !関数のオーバーロード
LET xx=0.5*LOG(x1*x1+y1*y1) !LOG(r)+i*θ、-π<θ<=π
LET yy=CompARG(x1,y1)
LET x=xx
LET y=yy
END SUB
!補助ルーチン ※多桁の関数
EXTERNAL FUNCTION ATN2(x) !アークタンジェント (-π/2,π/2)
IF x>1 THEN
LET cSGN=1
LET x=1/x
ELSEIF x<-1 THEN
LET cSGN=-1
LET x=1/x
ELSE
LET cSGN=0
END IF
LET a=0
FOR i=1500 TO 1 STEP -1 !※繰り返し回数は調整が必要である
LET a0=a
LET a=(i*i*x*x)/(2*i+1 + a)
IF ABS(a-a0)<=EPS(0) THEN EXIT FOR
NEXT i
IF cSGN>0 THEN
LET ATN2=PI/2-x/(1+a)
ELSEIF cSGN<0 THEN
LET ATN2=-PI/2-x/(1+a)
ELSE
LET ATN2=x/(1+a)
END IF
END FUNCTION
MERGE "EXP.LIB" !指数関数 ※級数展開で関数を計算する
MERGE "LOG.LIB" !対数関数
MERGE "TRIGONOM.LIB" !三角関数(正弦,余弦,正接)
!演算関連 べき乗、関数など
EXTERNAL SUB CompPowN(x1,y1, n, x,y) !べき乗 (x1+y1*i) ^ n → x+y*i
DECLARE EXTERNAL FUNCTION SIN,COS !関数のオーバーロード
LET r=CompABS(x1,y1) !r,θ
LET th=CompARG(x1,y1)
LET t=r^n !z^n=r^n*(COS(n*θ)+i*SIN(n*θ))、r=SQR(x1*x1+y1*y1)
LET x=t*COS(n*th)
LET y=t*SIN(n*th)
END SUB
EXTERNAL SUB CompNPow(n, x1,y1, x,y) !べき乗 n ^ (x1+y1*i) → x+y*i
DECLARE EXTERNAL FUNCTION LOG !関数のオーバーロード
CALL CompMul(LOG(n),0, x1,y1, a,b) !n^z1=exp(log(n)*z1)より
CALL CompEXP(a,b, x,y)
END SUB
EXTERNAL SUB CompSIN(x1,y1, x,y) !三角関数 正弦
DECLARE EXTERNAL FUNCTION EXP,SIN,COS !関数のオーバーロード
!sin(x+yi)
!={exp(x*i-y)-exp(-x*i+y)}/(2*i) ※sin(z)=(exp(i*z)-exp(-i*z))/(2*i)より
!={exp(-y)*(cos(x)+i*sin(x))-exp(y)*(cos(x)-i*sin(x))}/(2*i) ※exp(i*x)=cos(x)+i*sin(x)より
!={(exp(y)-exp(-y))*(-cos(x)) + (exp(y)+exp(-y))*sin(x)*i}/(2*i)
!={(exp(y)-exp(-y))*cos(x)*i + (exp(y)+exp(-y))*sin(x)}/2
LET e=EXP(y1)
LET f=1/e
LET yy=0.5*(e-f)*COS(x1)
LET xx=0.5*(e+f)*SIN(x1)
LET x=xx
LET y=yy
END SUB
EXTERNAL SUB CompCOS(x1,y1, x,y) !三角関数 余弦
DECLARE EXTERNAL FUNCTION EXP,SIN,COS !関数のオーバーロード
LET e=EXP(y1) !(exp(i*z)+exp(-i*z))/2
LET f=1/e
LET yy=0.5*(f-e)*SIN(x1)
LET xx=0.5*(f+e)*COS(x1)
LET x=xx
LET y=yy
END SUB
EXTERNAL SUB CompTAN(x1,y1, x,y) !三角関数 正接
DECLARE EXTERNAL FUNCTION EXP,SIN,COS !関数のオーバーロード
LET e=EXP(2*y1)
LET f=1/e
LET d=COS(2*x1)+0.5*(e+f)
LET x=SIN(2*x1)/d
LET y=(e-f)/d
END SUB
!逆三角関数
! ArcSin(z)=-i*LOG(SQR(1-z^2)+z*i)
! ArcCos(z)=-i*LOG(z+i*SQR(1-z^2))
! ArcTan(z)=i/2*LOG((i+z)/(i-z))
EXTERNAL SUB CompSinh(x1,y1, x,y) !双曲線正弦
DECLARE EXTERNAL FUNCTION EXP,SIN,COS !関数のオーバーロード
LET e=EXP(x1)
LET f=1/e
LET xx=0.5*(e-f)*COS(y1)
LET yy=0.5*(e+f)*SIN(y1)
LET x=xx
LET y=yy
END SUB
EXTERNAL SUB CompCosh(x1,y1, x,y) !双曲線余弦
DECLARE EXTERNAL FUNCTION EXP,SIN,COS !関数のオーバーロード
LET e=EXP(x1)
LET f=1/e
LET xx=0.5*(e+f)*COS(y1)
LET yy=0.5*(e-f)*SIN(y1)
LET x=xx
LET y=yy
END SUB
EXTERNAL SUB ComppTanh(x1,y1, x,y) !双曲線正接
DECLARE EXTERNAL FUNCTION EXP,SIN,COS !関数のオーバーロード
LET e=EXP(2*x1)
LET f=1/e
LET d=0.5*(e+f)+COS(2*y1)
LET y=SIN(2*y1)/d
LET x=0.5*(e-f)/d
END SUB
!ASCII,JISコード表
SET bitmap SIZE 501,501
SET WINDOW -1.5,16.5,16,-2
FOR i=0 TO 15 !行番号
PLOT TEXT ,AT -1,i: BSTR$(i,16)
NEXT i
FOR i=0 TO 15 !列番号
PLOT TEXT ,AT i,-1: BSTR$(i,16)
NEXT i
SET TEXT COLOR 4
FOR c=32 TO 255 !文字の表示
WHEN EXCEPTION IN
PLOT TEXT ,AT MOD(c,16),INT(c/16): CHR$(c)
USE
PRINT c !使用不可コード ※MS漢字(2バイト文字)の先頭
END WHEN
NEXT c
SET TEXT font "Wingdings",12
!SET TEXT font "symbol",12
SET TEXT COLOR 1
FOR c=32 TO 255 !フォントの表示
WHEN EXCEPTION IN
PLOT TEXT ,AT MOD(c,16)+0.2,INT(c/16)+0.4: CHR$(c)
USE
PRINT c
END WHEN
NEXT c
END
!x^2*(d2y/dx2)+x*(dy/dx)+(x^2-a^2)*y=0 …ベッセル
!x^2*(d2y/dx2)+x*(dy/dx)-(x^2+a^2)*y=0 …変形ベッセル
!-------------------------------
OPTION ARITHMETIC NATIVE
OPTION BASE 0
SET TEXT background "opaque"
DIM col(4), y0(4)
MAT READ col
DATA 4,10,2,14, 12 ! 0次 〜4次の色分け
!-----------------------------------------------------------------------
!0白 1黒
2青 3
緑 4赤 5水
色 6黄
色 7赤紫
! 8灰色 9濃い青 10濃い緑 11青緑 12えび茶 13オリーブ色 14濃い紫 15銀色
!-----------------------------------------------------------------------
SUB Dji( oddy,ody, iddy,idy,y)
LET oddy=-( x*idy +(sj*x^2-a^2)*y)/x^2 ! ddy=(d2y/dx2) :sj=1(ベッセル)
LET ody=-(x^2*iddy+(sj*x^2-a^2)*y)/x ! dy= (dy/dx) :sj=-1(変形ベッセル)
END SUB
SUB RungeKutta
CALL Dji( oddy1,ody1, iddy, idy, y)
CALL Dji( oddy2,ody2, iddy, idy+oddy1*dx/2, y+ody1*dx/2)
CALL Dji( oddy3,ody3, iddy, idy+oddy2*dx/2, y+ody2*dx/2)
CALL Dji( oddy4,ody4, iddy, idy+oddy3*dx , y+ody3*dx )
LET y=y+(ody1+2*ody2+2*ody3+ody4)*dx/6
LET idy=idy+(oddy1+2*oddy2+2*oddy3+oddy4)*dx/6
LET iddy=oddy4
END SUB
LET dx=.0005 !pitch
LET y0(0)=1 !yの初期値
LET y0(1)= 0.708248*dx
LET y0(2)=-1.2017 *dx^2
LET y0(3)=-0.015 *dx^3
LET y0(4)= 0.00615 *dx^4
!-----
LET sj=-1
LET m$="変形"
CALL window_
CALL Rk_bessel !変形ベッセルの微分方程式( ルンゲクッタ描画 )
CALL fn_bessel !変形ベッセル関数1種 In(x)
WAIT DELAY 2
!-----
LET sj=1
LET m$=""
CALL window_
CALL Rk_bessel ! ベッセルの微分方程式( ルンゲクッタ描画 )
CALL fn_bessel ! ベッセル関数1種 Jn(x)
SUB window_
CLEAR
IF sj=1 THEN !----ベッセル
LET h=1
LET l=-1
LET xr=20
SET WINDOW -3,xr, l, h
DRAW grid(xr/4,h/5)
ELSEIF sj=-1 THEN !----変形ベッセル
LET h=4
LET l=-1.5
LET xr=4
SET WINDOW -0.3,xr, l, h
DRAW grid(xr/8,h/8)
END IF
ASK PIXEL SIZE(0,0;xr,0) px,py
LET ss=Xr/px
END SUB
!-------------------- 微分方程式のルンゲクッタ描画
SUB Rk_bessel
SET TEXT COLOR 4
PLOT TEXT,AT (.325+.225*sj)*xr,.9*h-(.2-.04*sj)*(h-l) :"ルンゲクッタ描画"
FOR a=0 TO 4
LET y=y0(a)
LET idy=0
LET iddy=0
SET LINE COLOR "gray" !col(a+4)
SET TEXT COLOR "gray" !col(a+4)
PLOT TEXT,AT .1*xr,.9*h-.04*(h-l)*a :m$& "ベッセルの微分方程式 "& STR$(a)& "次"
!------------
FOR x=dx TO xr+dx STEP dx
PLOT LINES: x,y; ! PEN-on
IF FP(x)< dx THEN PRINT USING"##.## ###.######":x,y
CALL RungeKutta
NEXT x
!------------
PLOT LINES !PEN-off
PRINT
NEXT a
END SUB
!********************* 解のベッセル関数を重ねて照合する。
SUB fn_bessel
SET TEXT COLOR 1
PLOT TEXT,AT (.325+.225*sj)*xr,.9*h-(.2-.04*sj)*(h-l) :"関数で、重ね書き"
FOR n=0 TO 4
SET LINE COLOR col(n)
SET TEXT COLOR col(n)
PLOT TEXT,AT .1*xr,.9*h-.04*(h-l)*n :m$& "ベッセル関数1種 "& STR$(n)& "次 "
!------------画素間隔のStep
FOR x=dx TO xr+ss STEP ss
PLOT LINES: x,bessel(n,x); ! PEN-on
IF FP(x)< ss AND
dx< x THEN PRINT USING"##.## ###.######":IP(x),bessel(n,IP(x))
NEXT x
!------------
PLOT LINES !PEN-off
PRINT
NEXT n
END SUB
!------- ベッセル関数 変形ベッセル関数
FUNCTION bessel(n,x)
LET m=2*INT( (6+MAX(n,1.5*ABS(x))+9*1.5*ABS(x)/(1.5*ABS(x)+2))/2)
LET w=0
IF sj=1 THEN !---- ベッセル関数 Jn(x)
FOR k=1 TO m/2
LET w=w+Tk(k*2,x)
NEXT k
LET bessel=Tk(n,x)/(Tk(0,x)+2*w)
ELSEIF sj=-1 THEN !---- 変形ベッセル関数 In(x)
FOR k=1 TO m
LET w=w+Tk(k,x)
NEXT k
LET bessel=EXP(x)*Tk(n,x)/(Tk(0,x)+2*w)
END IF
END FUNCTION
FUNCTION Tk(i,x)
LET t2=0
LET t1=1e-9
LET t0=2*(m+1)/x*t1-sj*t2
FOR kp1=m TO i+1 STEP -1
LET t2=t1
LET t1=t0
LET t0=2*kp1/x*t1-sj*t2
NEXT kp1
LET Tk=t0
END FUNCTION
!半無限区間積分 ∫[0,∞]{EXP(-x)*f(x)}dx
DEF F(X)=1/(1-EXP(-X)) - 1/X
LET S=0
FOR I=1 TO 20
READ X,W
LET S=S+W*F(X)
NEXT I
PRINT S
DATA .0705398896919888, 1.6874680185111386E-01 !ガウス・ラゲール則の係数(分点、重み)
DATA .3721268180016114, 2.9125436200606828E-01 !20次ラゲール多項式より
DATA .9165821024832736, 2.6668610286700129E-01
DATA 1.7073065310283439, 1.6600245326950684E-01
DATA 2.7491992553094321, 7.4826064668792371E-02
DATA 4.0489253138508869, 2.4964417309283221E-02
DATA 5.6151749708616165, 6.2025508445722368E-03
DATA 7.4590174536710633, 1.1449623864769082E-03
DATA 9.5943928695810968, 1.5574177302781197E-04
DATA 12.0388025469643163, 1.5401440865224916E-05
DATA 14.8142934426307400, 1.0864863665179824E-06
DATA 17.9488955205193760, 5.3301209095567148E-08
DATA 21.4787882402850110, 1.7579811790505820E-09
DATA 25.4517027931869055, 3.7255024025123209E-11
DATA 29.9325546317006120, 4.7675292515781905E-13
DATA 35.0134342404790000, 3.3728442433624384E-15
DATA 40.8330570567285711, 1.1550143395003988E-17
DATA 47.6199940473465021, 1.5395221405823436E-20
DATA 55.8107957500638989, 5.2864427255691578E-24
DATA 66.5244165256157538, 1.6564566124990233E-28
END
!N個の電球
!1〜Nの番号の付いた電球がある。
!各電球にはスイッチがあり、点灯/消灯(ON/OFF)させることができる。
!1≦i≦Nに対して、i回目にiの倍数の電球の点灯/消灯(ON/OFF)させる。
!すべて消灯の状態から始めて、最後に点灯(ON)している電球の数は?
!倍数、約数の個数、エラトステネスの篩、素数
SET bitmap SIZE 601,601
SET WINDOW -1,50,50,-1
LET N=2009 !個数
DIM A(N)
MAT A=ZER !全消灯 ⇒倍数、約数の個数
!!!MAT A=CON !全点灯 ⇒エラトステネスの篩、素数
FOR i=1 TO N !i回目
FOR k=1 TO N !倍数にあたる電球に対して
LET t=k*i
IF t>N THEN EXIT FOR
LET A(t)=MOD(A(t)+1,2) !点灯/消灯
!!!LET A(t)=A(t)+1 !カウンタ ⇒約数の個数
!!!LET A(t)=0 !消灯のみ ⇒エラトステネスの篩、素数
NEXT k
!MAT PRINT A; !debug
SET DRAW mode hidden !ちらつき防止開始
CLEAR
FOR p=0 TO N-1
IF A(p+1)=1 THEN
DRAW disk WITH SCALE(0.5)*SHIFT(MOD(p,50),INT(p/50))
ELSE
DRAW circle WITH SCALE(0.5)*SHIFT(MOD(p,50),INT(p/50))
END IF
NEXT p
PLOT TEXT ,AT 2,48: STR$(i)&"の倍数"
SET DRAW mode explicit !ちらつき防止終了
NEXT i
LET c=0 !点灯している個数
FOR i=1 TO N
IF A(i)=1 THEN LET c=c+1
NEXT i
PRINT c;"個"
PRINT INT(SQR(N)) !検算 平方数の数
END
!定数
LET Vcc=1 !プラス電源
LET GND=0 !GND電位
LET ON_=GND !アノード:Vcc
LET OFF_=Vcc
LET h=8 !行方向の電球の数
LET w=5*h !列方向
DIM L(h,w) !電球の状態
MAT L=ZER !全消灯
SET bitmap SIZE w*20+1,h*20+1 !基盤の大きさ
SET WINDOW 0,w+1,h+1,0
DRAW grid(2,2)
DIM P(h,w)
!●フロー、シフト型
LET m=8
FOR x=1 TO w !初期状態
LET v=(m-1)-MOD(x-1,m) !のこぎり波
FOR y=1 TO h
LET L(y,x)=v
NEXT y
NEXT x
MAT PRINT L;
FOR t=1 TO 50 !駆動回路
FOR y=1 TO h !0と1に復号化する
FOR x=1 TO w
LET L(y,x)=MOD(L(y,x)+1,m) !右方向へ移動させる (k+1) mod m
!!!IF L(y,x)=m-1 THEN LET P(y,x)=ON_ ELSE LET P(y,x)=OFF_ !道路工事
IF L(y,x)>=m-3 THEN LET P(y,x)=ON_ ELSE LET P(y,x)=OFF_ !道路工事2
NEXT x
NEXT y
DRAW LEDmatrix(P,h,w) !電球を光らせる
WAIT DELAY 0.3
NEXT t
!●シャッター型
LET m=8
FOR x=1 TO w !初期状態
!!!LET v=(m-1)-MOD(x-1,m) !パターン1
LET v=(m-1)-MOD(x-1,m)-INT((x-1)/m) + INT(m/2) !パターン2
FOR y=1 TO h
LET L(y,x)=v
NEXT y
NEXT x
MAT PRINT L;
!!!LET m=m+1!パターン1
LET m=m+1 + INT(m/2) !パターン2
LET n=m
FOR t=1 TO 50 !駆動回路
LET n=MOD(n-1,m)
FOR y=1 TO h !0と1に復号化する
FOR x=1 TO w
IF L(y,x)>=n THEN LET P(y,x)=ON_ ELSE LET P(y,x)=OFF_ !閾値
NEXT x
NEXT y
DRAW LEDmatrix(P,h,w) !電球を光らせる
WAIT DELAY 0.3
NEXT t
!電子部品(配置と配線)
PICTURE LEDmatrix(L(,),m,n) !m行n列マトリクス
SET DRAW mode hidden !ちらつき防止開始
CLEAR
FOR x=1 TO n !ダイナミック点灯(個々に点灯させる)
FOR y=1 TO m
DRAW LED(Vcc,L(y,x)) WITH SHIFT(x,y)
NEXT y
NEXT x
SET DRAW mode explicit !ちらつき防止終了
END PICTURE
!電子部品(下位)
! a │
! ▼→
! k T
! │
PICTURE LED(a,k) !発光ダイオードを表示する
IF a=1 AND k=0 THEN
DRAW disk WITH SCALE(0.5) !点灯
ELSE
DRAW circle WITH SCALE(0.5) !消灯
END IF
END PICTURE
END
OPTION ARITHMETIC NATIVE
!2重指数関数型数値積分(Double Exponential formula)
! ∫[0,∞]f(x)dx 半無限領域(0,∞)の積分
!
! x=EXP(t-EXP(-t))とすると、dx/dt=EXP(t-EXP(-t))*(1+EXP(-t))
! 与式=∫[-∞,∞]{f(EXP(t-EXP(-t)))*EXP(t-EXP(-t))*(1+EXP(-t))}dt
DEF f(x)=EXP(-x)/(1-EXP(-x)) - EXP(-x)/x !∫[0,∞]f(x)dx = 0.5772156649015328606… オイラーの定数γ
LET N=36 !分割数
LET h=1/6
LET s=0
FOR j=-N/2 TO N/2
LET t=j*h
LET v=EXP(-t)
LET x=EXP(t-v)
LET s=s + f(x)*x*(1+v)
NEXT j
LET s=h*s
PRINT s !結果を表示する
!2重指数関数型数値積分(Double Exponential formula)
! ∫[0,∞]f(x)dx 半無限領域(0,∞)の積分
!
! x=EXP(PI*SINH(t))とすると、dx/dt=EXP(PI*SINH(t))*PI*COSH(t)
! 与式=PI*∫[-∞,∞]{f(EXP(PI*SINH(t)))*EXP(PI*SINH(t))*COSH(t)}dt
DEF g(x)=1/(1+x^6) !∫[0,∞]g(x)dx = PI/3
LET N=64 !分割数
LET h=1/8
LET s=0
FOR j=-N/2 TO N/2
LET t=j*h
LET x=EXP(PI*SINH(t))
LET s=s + g(x)*x*COSH(t)
NEXT j
LET s=h*PI*s
PRINT s !結果を表示する
PRINT PI/3 !検算
!2重指数関数型数値積分(Double Exponential formula)
! ∫[-1,1]f(x)dx
!
! x=TANH(PI/2*SINH(t))とすると、dx/dt=PI/2*COSH(t)/COSH(PI/2*SINH(t))^2
! 与式=PI/2*∫[-∞,∞]{f(TANH(PI/2*SINH(t)))*COSH(t)/COSH(PI/2*SINH(t))^2}dt
DEF f2(x)=SQR(1-x^2)/(2-x) !∫[-1,1]f(x)dx = PI*(2-SQR(3))
LET N=64 !分割数
LET h=1/8
LET s=0
FOR j=-N/2 TO N/2
LET t=j*h
LET v=PI/2*SINH(t)
LET s=s + f2(TANH(v))*COSH(t)/COSH(v)^2
NEXT j
LET s=h*PI/2*s
PRINT s !結果を表示する
PRINT PI*(2-SQR(3)) !検算
END
!大幅に 改訂し、特に路面の描画を改善した、が、次の問題が解けない。
!見え隠れする路面の裏側を、別な色で塗るには、どうすれば、よいか?
!------------
! ハイウェイ
!------------
!SET bitmap SIZE 671,671
DIM Mp(4,4) !視点からの被写体の相対座標(一点投影用)
DIM Xz(4,4),zY(4,4) !XY_Xz変換, XY_zY変換
DIM XYz(4,4) !XY平面のz平行移動
!
!※投影面の裏側に、操作対象が有るので、座標は左手系(Z軸が裏向き)です。
! 投影面を、車両前縁d に置き、Z=1.5 、視点 Z=0 が 手前。
! 視点 Z=0 を頂点に、投影面 Z=1.5 へ 一点投影。面中心から±1を画面とし、
! 外界面を、投影面 前方+170 から、投影面 Z=1.5 までを、奥から描く。
!-------------------------------------------------------------------------
! 一点投影用 Mp
!
!原画_行ベクトル Mp 表示_行ベクトル
! (X,Y,Z,1)|1 0 0 0| →(X+x,Y+y, * ,Z+z) の4列目 Z+z で縮小。
! |0
1 0
0|
↓
! |0
0 0 1| 座標
(X+x)/(Z+z),(Y+y)/(Z+z) の描点群。
! |x
y 0 z| *
印は「最終的表示で無効」のz座標。
MAT READ Mp
DATA 1,0,0,0 !小文字 x y z は、視点から、道路左端の相対座標。
DATA 0,1,0,0
DATA 0,0,0,1 !変形指示 MAT 文で効果する。
DATA 0,0,0,0
!-------------------------------------------------------------------------
! 道路など、画面に垂直な広がりは、以下の Xz zY XYz 行列を、先に通します。
! 上の原画の Z は通常0ですが、以下の様に 変形を行なうと、発生します。
!-------------------------------------------------------------------------
!<路面>の原画用 Xz XY平面→ XZ平面として描く。
!
!原画_行ベクト
ル
新しい原画_行ベクトル
! (X,Y,0,1)|1 0 0 0| →(X+Y*dxdz, Y*dydz, Y, 1)
! |dxdz dydz 1 0|
! |0 0 0
0| dxdz: Z軸カーブの微分 dx/dz
! |0 0 0
1| dydz: Z軸ピッチの微分 dy/dz
MAT READ Xz
DATA 1,0,0,0
DATA 0,0,1,0
DATA 0,0,0,0
DATA 0,0,0,1
!-------------------------------------------------------------------------
!<建物>の原画用 zY XY平面→ ZY平面として描く。
!
!原画_行ベクト
ル
新しい原画_行ベクトル
! (X,Y,0,1)|dxdz 0 1 0| →(X*dxdz+x, Y, X, 1)
! |0 1 0
0|
! |0 0 0
0| dxdz: Z軸カーブの微分 dx/dz
! |x 0 0
1| x: ZY平面のx座標
MAT READ zY
DATA 0,0,1,0
DATA 0,1,0,0
DATA 0,0,0,0
DATA 0,0,0,1
!-------------------------------------------------------------------------
!<建物>の原画用 XYz XY平面の Z軸移動。
!
!原画_行ベクト
ル
新しい原画_行ベクトル
!
(X,Y,0,1)|1 0 0
0| →(X+(dxdz)*z, Y, z, 1)
! |0 1 0
0|
! |0 0 0
0| dxdz: Z軸カーブの微分 dx/dz
! |(dxdz)*z
0 z
1| z: Z軸 移動差分
MAT READ XYz
DATA 1,0,0,0
DATA 0,1,0,0
DATA 0,0,0,0
DATA 0,0,0,1
!-------------------------------------------------------------------------
!
DEF v(t)=v0+a*t !速度
DEF I_v(t)=v0*t+a*t*t/2 !移動距離 ∫v(t)dt
!
DEF yaw(z)= 10*SIN((z-2)*0.1) !カーブ、横の偏差 x(z)
DEF d_yaw(z)= COS((z-2)*0.1) !カーブ、微分係数 dx/dz
DEF pitch(z)= 5*SIN(z*0.1) !ピッチ、縦の偏差 y(z)
DEF d_pitch(z)= 0.5*COS(z*0.1) !ピッチ、微分係数 dy/dz
!
SET WINDOW -1,1,-1,1 !画面スケール±1
LET
v0=15
!初速度
LET
a=-v0^2/2/100
!減速加速度, -v0^2/2/移動距離
LET t0=TIME
DO
LET t=TIME-t0
IF t>tb+0.15 THEN
LET tb=t
LET
d=I_v(t) !車両前縁d のz座標
PRINT USING "時間=###.## 速度=###.## 走行距離=###.##":t,v(t),d
SET DRAW mode hidden !裏ページに書く
CALL
Animation !
描画
SET DRAW mode explicit !裏ページの表示
END IF
MOUSE POLL msx,msy,mlb,mrb
LOOP UNTIL v(t)<=0 OR mrb=1
SUB Animation
!----sky
SET AREA COLOR 17
PLOT AREA:-1,0; 1,0; 1,1; -1,1
!----ground
SET AREA COLOR 42
PLOT AREA:-1,0; 1,0; 1,-1; -1,-1
!----guide message
SET TEXT COLOR 1
SET TEXT FONT "",11
PLOT TEXT,AT.35,.9:"右クリック保持 Stop"
SET TEXT COLOR 0
SET TEXT FONT "",90
!----
LET ss=5/2
FOR i=IP((d+170)/ss)*ss TO d STEP -ss
LET
Mp(4,1)= yaw(i)-yaw(d) -1.5
!投影面中心線から 道路左端のx座標
LET Mp(4,2)=pitch(i)-pitch(d)-1.5 !投影面中心線から 道路左端のy座標
LET
Mp(4,4)=
i-d +1.5 !投影面の後方1.5 から道路左端のz座標
!----
!
1
,0
,0
, 0|
!
0
,1
,0
, 0|
!
0
,0
,0
, 1|
! yaw(i)-yaw(d)-1.5
,pitch(i)-pitch(d)-1.5
,0 ,i-d+1.5|
!----
IF MOD(i,10)=0 THEN
DRAW Building( 0-2,-9, -3,20,-2 ) WITH Mp !x,y, W,H,D
DRAW Building( 6+2,-9, -3,19, 2.5) WITH Mp !x,y, W,H,D
DRAW Sign WITH Mp
END IF
IF MOD(i,10)=5 THEN DRAW Tree WITH Mp
DRAW Road(-.993*ss) WITH Mp
NEXT i
END SUB
PICTURE Building(x,y,w,h,d1)
IF d-i<=w THEN
!---back plane
LET zY(1,1)=d_yaw(i+w/2) !Z軸カーブの微分 dx/dz
LET
zY(4,1)=x+d1
!ZY平面のx座標
DRAW Wall((y),w,h) WITH zY
!---facade
LET
zY(4,1)=x !ZY平面のx座標
DRAW Wall((y),w,h) WITH zY
!---side plane
LET XYz(4,1)=d_yaw(i+w/2)*w !Z軸カーブによるx移動差分
LET
XYz(4,3)=w
!Z軸 移動差分
DRAW Side(x,y,h,d1) WITH XYz
END IF
END PICTURE
!
PICTURE Wall(y,w,h)
SET AREA COLOR 8 !gray
PLOT AREA: 0,y; w,y; w,y+h; 0,y+h !(Z,Y)平面として描く。
FOR y=y+h-.5 TO y+1 STEP -2.5
PLOT LINES: 0,y;
w,y !
(Z,Y)平面として描く。
NEXT y
END PICTURE
!
PICTURE Side(x,y,h,d1)
SET AREA COLOR 16 !dark gray
PLOT AREA: x,y; x+d1,y; x+d1,y+h; x,y+h !移動前(X,Y)平面として描く。
END PICTURE
PICTURE Road(e)
IF e< d-i THEN LET e=d-i
LET Xz(2,1)=d_yaw(i+e/2) !Z軸カーブの微分 dx/dz
LET Xz(2,2)=d_pitch(i+e/2) !Z軸ピッチの微分 dy/dz
DRAW Surface(e) WITH Xz
END PICTURE
!
PICTURE Surface(e)
SET AREA COLOR 15
PLOT AREA: 0,0; 6,0; 6,e; 0,e !(X,Z)平面として描く。
!---center line
SET AREA COLOR 0
PLOT AREA: 2.9,0; 2.9,e; 3.1,e; 3.1,0 !(X,Z)平面として描く。
!---joint line
PLOT LINES: 0 ,0; 2.9,0
PLOT LINES: 3.1,0; 6 ,0
END PICTURE
PICTURE Tree
SET AREA COLOR 12 !幹
PLOT AREA:-0.075,0; 0.075,0; 0.025,3;-0.025,3
SET AREA COLOR 10
FOR w=1 TO 7 !葉
DRAW disk WITH SCALE(0.3+0.05-RND*0.1)*SHIFT(0.4-RND*0.8, 2.7+0.325-RND*0.75)
NEXT W
END PICTURE
PICTURE Sign
IF MOD(i,50)=0 THEN SET AREA COLOR 2 ELSE SET AREA COLOR 4
PLOT AREA:-0.025,0; 0.025,0; 0.025,2;-0.025,2 !pole
DRAW disk WITH SCALE(0.5)*SHIFT(0,2) !plate
!PLOT TEXT,AT -.35,1.74,USING ">%%":STR$(i) !sign
CALL Plot_7segment(0 ,2 ,0.15 ,STR$(i)) !sign( PLOT TEXT が重い時)
END PICTURE
SUB Plot_7segment(x,y,s,i$) !文字列中心(x,y) 文字の横幅(s) 数字の文字列(i$)
SET LINE COLOR 0
SET LINE width 9/(i-d+1.5) !一点投影・縮小の補償。(線幅は MAT 文で縮まない)
LET w=LEN(i$)
LET s1=s ! y軸↑:s1=s y軸↓:s1=-s
LET s2=s/2
LET x=x-(w-1)*s2*1.6
FOR p=1 TO w
SELECT CASE VAL(i$(p:p))
CASE 0
PLOT LINES:x-s2,y+s;x-s2,y-s;x+s2,y-s;x+s2,y+s;x-s2,y+s
CASE 1
PLOT LINES:x,y-s;x,y+s
CASE 2
PLOT LINES:x-s2,y+s1;x+s2,y+s1;x+s2,y;x-s2,y;x-s2,y-s1;x+s2,y-s1
CASE 3
PLOT LINES:x-s2,y-s;x+s2,y-s;x+s2,y+s;x-s2,y+s
PLOT LINES:x-s2,y;x+s2,y
CASE 4
PLOT LINES:x-s2,y+s1;x-s2,y;x+s2,y
PLOT LINES:x+s2,y+s1;x+s2,y-s1
CASE 5
PLOT LINES:x+s2,y+s1;x-s2,y+s1;x-s2,y;x+s2,y;x+s2,y-s1;x-s2,y-s1
CASE 6
PLOT LINES:x+s2,y+s1;x-s2,y+s1;x-s2,y-s1;x+s2,y-s1;x+s2,y;x-s2,y
CASE 7
PLOT LINES:x-s2,y+s1;x+s2,y+s1;x+s2,y-s1
CASE 8
PLOT LINES:x-s2,y;x-s2,y-s;x+s2,y-s;x+s2,y+s;x-s2,y+s;x-s2,y;x+s2,y
CASE 9
PLOT LINES:x+s2,y;x-s2,y;x-s2,y+s1;x+s2,y+s1;x+s2,y-s1;x-s2,y-s1
CASE ELSE
END SELECT
LET x=x+s*1.6
NEXT p
SET LINE width 1
SET LINE COLOR 1
END SUB
!インベーダー・ゲーム
DEF V2W(x)=4*x !仮想画面の座標を物理画面の座標へ
DEF W2V(x)=INT(x/4) !その逆
PICTURE DOT !物理画面にドットを表示する
PLOT AREA: -2,-2; 2,-2; 2,2; -2,2 !4x4
END PICTURE
LET vx=180 !仮想画面の大きさ 150×180ドット
LET vy=150
SET bitmap SIZE V2W(vx)+1,V2W(vy)+1 !物理画面の大きさ
SET WINDOW 0,V2W(vx),V2W(vy),0 !スクリーン座標
RANDOMIZE
!------------------------------ 弾
DATA "* " !コマ1 弾1
DATA " *"
DATA "* "
DATA " *" !コマ2
DATA "* "
DATA " *"
DIM bm$(1,2) !弾 3×2ドット
CALL ReadPattern(1,3, bm$)
LET NumOfBeam=5 !弾 最大数5
DIM BM(NumOfBeam,3)
MAT BM=(-1)*CON
!------------------------------ インベーダー
LET m=8 !m×nドット
LET n=11
DATA "** **" !コマ1 機体0
DATA "* *"
DATA " "
DATA " "
DATA " "
DATA " "
DATA "* *"
DATA "** **"
DATA " " !コマ2
DATA "* * * *"
DATA " * * * * "
DATA " * * "
DATA "** **"
DATA " * * "
DATA " * * * * "
DATA "* * * *"
DATA " * * " !コマ1 機体1
DATA "* * * *"
DATA "* ******* *"
DATA "*** *** ***"
DATA "***********"
DATA " ********* "
DATA " * * "
DATA " * * "
DATA " * * " !コマ2
DATA " * * "
DATA " ******* "
DATA " ** *** ** "
DATA "***********"
DATA "* ******* *"
DATA "* * * *"
DATA " ** ** "
DATA " *** " !コマ1 機体2
DATA " ***** "
DATA " ******* "
DATA " ** *** ** "
DATA " ********* "
DATA " * * "
DATA " * * * * "
DATA " * * * * "
DATA " *** " !コマ2
DATA " ***** "
DATA " ******* "
DATA " ** *** ** "
DATA " ********* "
DATA " * *** * "
DATA " * * "
DATA " * * "
DATA " " !コマ1 機体3
DATA " *** "
DATA " ********* "
DATA "** *** **"
DATA "***********"
DATA " ***** "
DATA " ** * ** "
DATA "** **"
DATA " " !コマ2
DATA " *** "
DATA " ********* "
DATA "** *** **"
DATA "***********"
DATA " ** ** "
DATA " * * "
DATA " * * "
DIM ptn$(4,2) !パターン(1機×2コマ)で読み込む
CALL ReadPattern(4,m, ptn$)
SUB ReadPattern(n,l, ptn$(,))
FOR k=1 TO n !各機体
FOR j=1 TO 2 !各コマ
LET v$=""
FOR i=1 TO l
READ s$
LET v$=v$&s$
NEXT i
LET ptn$(k,j)=v$ !登録する
NEXT j
NEXT k
END SUB
!------------------------------ 編隊
LET p=6 !p×q
LET q=8
DIM F(p+1,q) !0以上:生存フラグ、パターン番号
MAT F=ZER
DATA 4, 4, 4, 4, 4, 4, 4, 4 !パターン番号 ※偶数
DATA 4, 4, 4, 4, 4, 4, 4, 4
DATA 6, 6, 6, 6, 6, 6, 6, 6
DATA 6, 6, 6, 6, 6, 6, 6, 6
DATA 2, 2, 2, 2, 2, 2, 2, 2
DATA 2, 2, 2, 2, 2, 2, 2, 2
DATA 6, 6, 6, 6, 6, 6, 6, 6 !先頭の番号
MAT READ F
LET ox=n+2 !機体の間隔
LET oy=m+2
LET lx=vx-ox*q !編隊の左上位置
LET ly=4
PICTURE BLOCK(v$,m,n) !インベーダーなどを位置(0,0)-(n,m)に表示する
FOR i=0 TO m-1 !m×nドット
FOR j=0 TO n-1
LET k=i*n+j+1
IF v$(k:k)<>" " THEN DRAW DOT WITH SHIFT(V2W(j),V2W(i))
NEXT j
NEXT i
END PICTURE
LET DX=-1 !移動方向
LET FLG=0 !機体の動作
LET Invaded=0 !侵略状況
DO !ゲームループ
!------------------------------ 当り判定(仮)
MOUSE POLL mx,my,left,right !マウスの状態を得る
IF left=1 THEN !左ボタン押下なら
LET x=W2V(mx)-lx !編隊の領域内なら
LET y=W2V(my)-ly
IF x<0 OR x>=ox*q OR y<0 OR y>=oy*p THEN
ELSE
LET xx=MOD(x,ox) !機体内なら
LET yy=MOD(y,oy)
IF xx<n AND yy<m THEN
LET xx=INT(x/ox)+1 !該当する機体を爆発→消滅する
LET yy=INT(y/oy)+1
IF F(yy,xx)>=2 THEN LET F(yy,xx)=1
END IF
END IF
END IF
!------------------------------ 描画処理毎(フレームを表示する)
SET DRAW mode hidden !ちらつき防止開始
CLEAR
LET CntOfEnemy=0
FOR x=1 TO q !インベーダー群を表示する
IF F(p+1,x)>0 THEN !この列に機体が存在するなら
LET xx=lx+ox*(x-1)
LET F(p+1,x)=0
FOR y=1 TO p
LET ptn=F(y,x) !生存なら
IF ptn>=0 THEN
LET idx=INT(ptn/2) !パターンを選択する
LET koma=MOD(ptn,2)
DRAW BLOCK(ptn$(idx+1,koma+1),m,n) WITH SHIFT(V2W(xx),V2W(ly+oy*(y-1)))
IF ptn=1 THEN
LET F(y,x)=-1 !爆発→消滅
ELSE
LET F(y,x)=MOD(ptn+1,2)+idx*2 !ぱたぱたアニメーション
LET F(p+1,x)=y !先頭の番号を更新する
IF ly+oy*(y-1)>vy*2/3 THEN LET Invaded=1 !侵略したなら
END IF
LET CntOfEnemy=CntOfEnemy+1 !機体の数
END IF
NEXT y
IF F(p+1,x)>0 THEN !この列に機体があれば
IF FLG=0 THEN !折り返しを確認する
IF xx<=0 OR xx+n>=vx THEN LET FLG=1 !左端、右端なら
END IF
IF RND<0.1 THEN !弾を発射する
FOR y=1 TO NumOfBeam !未発射を探す
IF BM(y,3)<0 THEN
LET BM(y,1)=xx+INT(n/2)
LET BM(y,2)=ly+oy*(F(p+1,x)-1)+INT(m/2)
LET BM(y,3)=0 !使用中
EXIT FOR !1列に1つずつ
END IF
NEXT y
END IF
END IF
END IF
NEXT x
FOR y=1 TO NumOfBeam !弾を表示する
LET ptn=BM(y,3)
IF ptn>=0 THEN !使用中なら
DRAW BLOCK(bm$(1,ptn+1),3,2) WITH SHIFT(V2W(BM(y,1)),V2W(BM(y,2)))
LET BM(y,3)=MOD(ptn+1,2) !ぱたぱたアニメーション
END IF
NEXT y
SET DRAW mode explicit !ちらつき防止終了
!------------------------------ 移動処理(次のフレームへ)
SELECT CASE FLG !インベーダーを移動させる
CASE 0
LET lx=lx+DX !横へ移動させる
CASE 1
LET ly=ly+2 !折り返しの動作(降下させる)
LET FLG=2
CASE ELSE
LET DX=-DX !降下後、1つ離す
LET lx=lx+DX
LET FLG=0
END SELECT
FOR i=1 TO NumOfBeam !弾を移動させる
IF BM(i,3)>=0 THEN !使用中なら
LET BM(i,2)=BM(i,2)+3 !降下させる
IF BM(i,2)>vy THEN LET BM(i,3)=-1 !下端なら
END IF
NEXT i
!!!WAIT DELAY 0.3
LOOP UNTIL CntOfEnemy=0 OR Invaded=1 !機体全滅まで
END
懐かしいゲームです。「クリックしても弾が発射されない」と思いましたが、インベーダーを直接クリックするのですね。
編隊のすぐ右側をクリックすると「添字が範囲外」のエラーが生じることがあります。
当り判定のルーチンで xx=9 のとき IF F(yy,xx)>=2 THEN LET F(yy,xx)=1 がエラーとなるようです。
x=104 を回避すればよいので、IF x<0 OR x>ox*q OR y<0 OR y>oy*p THEN を
IF x<0 OR x>=ox*q OR y<0 OR y>oy*p THEN とするのはどうでしょうか。
!ブロック崩し
DEF V2W(x)=4*x !仮想画面の座標を物理画面の座標へ
DEF W2V(x)=INT(x/4) !その逆
PICTURE DOT !物理画面にドットを表示する
PLOT AREA: -2,-2; 2,-2; 2,2; -2,2 !4x4
END PICTURE
LET vx=100 !仮想画面の大きさ 120×100ドット
LET vy=120
SET bitmap SIZE V2W(vx)+1,V2W(vy)+1 !物理画面の大きさ
SET WINDOW 0,V2W(vx),V2W(vy),0 !スクリーン座標
RANDOMIZE
!------------------------------ ブロック
LET lx=5 !左上の座標
LET ly=20
LET ox=10 !間隔
LET oy=6
LET p=5 !p×q個
LET q=INT(vx/ox)-2
DIM B(0 TO p-1,0 TO q-1) !1:有、0:無
MAT B=2*CON
DIM BC(2) !衝突回数の色(ルックアップテーブル)
DATA 4,10
MAT READ BC
!------------------------------ 壁
LET wx1=lx-1 !左上の座標
LET wy1=ly-15
LET wx2=wx1+ox*q !右下の座標
LET wy2=vy-5
!------------------------------ パッド
LET px=x !左上の座標
LET pw=5 !幅の半分
!------------------------------ ボール
LET dx=3 !移動方向
LET dy=5
LET x1=INT((wx2-wx1)/2) !発射位置
LET y1=ly+oy*p + 10
LET x=x1 !現在の位置
LET y=y1
LET k=0
LET NumOfBlock=p*q !ブロックの総数
LET NumOfPad=3 !パッドの残り数
DO !ゲームループ
!------------------------------ 当り判定
IF (x<=wx1 AND x1<>wx1) THEN !左側の壁 ※2重衝突防止
!!!IF x<=wx1 THEN !左側の壁
LET k=0 !ボールの起点
LET x1=wx1
LET y1=y-INT((wx1-x)*dy/dx) !位置を補正 ※壁のすり抜け
LET x=x1 !ボールの位置
LET y=y1
LET dx=-dx !ボールの反射
END IF
IF (x>=wx2 AND x1<>wx2) THEN !右側の壁
!!!IF x>=wx2 THEN !右側の壁
LET k=0
LET x1=wx2
LET y1=y-INT((x-wx2)*dy/dx)
LET x=x1
LET y=y1
LET dx=-dx
END IF
LET xx=x-lx !ブロックの領域外なら
LET yy=y-ly
IF xx<0 OR xx>=ox*q OR yy<0 OR yy>=oy*p THEN
IF (y<=wy1 AND y1<>wy1) THEN !上側の壁
!!!IF y<=wy1 THEN !上側の壁
LET k=0
LET x1=x-INT((wy1-y)*dx/dy)
LET y1=wy1
LET x=x1
LET y=y1
LET dy=-dy
END IF
IF ABS(x-px)<=pw AND (y>=wy2 AND y1<>wy2) THEN !パッド
!!!IF ABS(x-px)<=pw AND y>=wy2 THEN !パッド
LET k=0
LET x1=x-INT((y-wy2)*dx/dy)
LET y1=wy2
LET x=x1
LET y=y1
LET dy=-dy
END IF
IF y>=vy THEN !ミス!!!
LET NumOfPad=NumOfPad-1
LET x=x1 !ボールの位置
LET y=y1
LET px=x !パッドの位置
WAIT DELAY 1
END IF
ELSE !領域内なら
!※ブロックを厚くするとボールが内部に入った状態になって、何重にも衝突したことになる。
LET xx=INT(xx/ox) !該当するブロックの位置を算出する
LET yy=INT(yy/oy)
IF B(yy,xx)>0 THEN !消滅させる
LET B(yy,xx)=B(yy,xx)-1
IF B(yy,xx)=0 THEN LET NumOfBlock=NumOfBlock-1
LET k=0
LET x1=x
LET y1=y
LET dy=-dy
END IF
END IF
!------------------------------ 描画処理毎(フレームを表示する)
SET DRAW mode hidden !ちらつき防止開始
CLEAR
SET AREA COLOR 1
FOR xx=wx1 TO wx2 !上側の壁を表示する
DRAW DOT WITH SHIFT(V2W(xx),V2W(wy1))
NEXT xx
FOR yy=wy1 TO wy2
DRAW DOT WITH SHIFT(V2W(wx1),V2W(yy)) !左側、
DRAW DOT WITH SHIFT(V2W(wx2),V2W(yy)) !右側
NEXT yy
FOR yy=0 TO p-1 !ブロック
FOR xx=0 TO q-1
LET c=B(yy,xx)
IF c>0 THEN !存在するなら
SET AREA COLOR BC(c) !ルックアップテーブルを参照する
DRAW BLOCK(oy-1,ox-1) WITH SHIFT(V2W(lx+ox*xx),V2W(ly+oy*yy))
END IF
NEXT xx
NEXT yy
SET AREA COLOR 1
DRAW BLOCK(2,2*pw) WITH SHIFT(V2W(px-pw),V2W(wy2)) !パッド ※中心の座標で
SET AREA COLOR 2
DRAW BLOCK(3,3) WITH SHIFT(V2W(x-1),V2W(y-1)) !ボール ※中心の座標で
SET DRAW mode explicit !ちらつき防止終了
!------------------------------ 移動処理(次のフレームへ)
IF ABS(dy)<ABS(dx) THEN !xの方が増分が多い
!□□□■
!□■■□ y=l*x+m の式として考える
!■□□□
LET k=k+SGN(dx) !±1 移動量 ※低解像度だとカクカク動くように見える
!!!LET k=k+SGN(dx)*3 !±3 移動量
LET x=x1+k
LET y=y1+INT(k*dy/dx)
ELSE !yの方が増分が多い
!□□■
!□■□ x=l*y+m の式として考える
!□■□
!■□□
LET k=k+SGN(dy) !±1 移動量
!!!LET k=k+SGN(dy)*3 !±3 移動量
LET x=x1+INT(k*dx/dy)
LET y=y1+k
END IF
LET px=x !パッド位置はボールの真下
!!!WAIT DELAY 0.2
LOOP UNTIL NumOfPad=0 OR NumOfBlock=0 !パッド、ブロックがなくなるまで
PICTURE BLOCK(m,n) !ブロックなどを位置(0,0)-(n,m)に表示する
PLOT AREA: -2,-2; 4*n-2,-2; 4*n-2,4*m-2; -2,4*m-2
END PICTURE
!PICTURE BLOCK(m,n) !ブロックなどを位置(0,0)-(n,m)に表示する
! FOR i=0 TO m-1 !m×nドット
! FOR j=0 TO n-1
! DRAW DOT WITH SHIFT(V2W(j),V2W(i))
! NEXT j
! NEXT i
!END PICTURE
END
!次の問題が解けなかったが、
!「見え隠れする路面の裏側を、別な色で塗る方法」が、見つかった。
!------------
! ハイウェイ
!------------
!SET bitmap SIZE 671,671 !← 大きい画面にするとき。(1024x768 にぴったり)
DIM Mp(4,4) !視点からの被写体の相対座標(一点投影用)
DIM Xz(4,4),zY(4,4) !XY_Xz変換, XY_zY変換
DIM XYz(4,4) !XY平面のz平行移動
!
!※投影面の裏側に、操作対象が有るので、座標は左手系(Z軸が裏向き)です。
! 投影面を、車両前縁d に置き、Z=1.5 、視点 Z=0 が 手前。
! 視点 Z=0 を頂点に、投影面 Z=1.5 へ 一点投影。面中心から±1を画面とし、
! 外界面を、投影面 前方+150 から、投影面 Z=1.5 までを、奥から描く。
!-------------------------------------------------------------------------
! 一点投影用 Mp
!
!原画_行ベクトル Mp 表示_行ベクトル
! (X,Y,Z,1)|1 0 0 0| →(X+x,Y+y, * ,Z+z) の4列目 Z+z で縮小。
! |0
1 0
0|
↓
! |0
0 0 1| 座標
(X+x)/(Z+z),(Y+y)/(Z+z) の描点群。
! |x
y 0 z| *
印は「最終的表示で無効」のz座標。
MAT READ Mp
DATA 1,0,0,0 !小文字 x y z は、視点から、道路左端の相対座標。
DATA 0,1,0,0
DATA 0,0,0,1 !変形指示 MAT 文で効果する。
DATA 0,0,0,0
!-------------------------------------------------------------------------
! 道路など、画面に垂直な広がりは、以下の Xz zY XYz 行列を、先に通します。
! 上の原画の Z は通常0ですが、以下の様に 変形を行なうと、発生します。
!-------------------------------------------------------------------------
!<路面>の原画用 Xz XY平面→ XZ平面として描く。
!
!原画_行ベクト
ル
新しい原画_行ベクトル
! (X,Y,0,1)|1 0 0 0| →(X+Y*dxdz, Y*dydz, Y, 1)
! |dxdz dydz 1 0|
! |0 0 0
0| dxdz: Z軸カーブの微分 dx/dz
! |0 0 0
1| dydz: Z軸ピッチの微分 dy/dz
MAT READ Xz
DATA 1,0,0,0
DATA 0,0,1,0
DATA 0,0,0,0
DATA 0,0,0,1
!-------------------------------------------------------------------------
!<建物>の原画用 zY XY平面→ ZY平面として描く。
!
!原画_行ベクト
ル
新しい原画_行ベクトル
! (X,Y,0,1)|dxdz 0 1 0| →(X*dxdz+x, Y, X, 1)
! |0 1 0
0|
! |0 0 0
0| dxdz: Z軸カーブの微分 dx/dz
! |x 0 0
1| x: ZY平面のx座標
MAT READ zY
DATA 0,0,1,0
DATA 0,1,0,0
DATA 0,0,0,0
DATA 0,0,0,1
!-------------------------------------------------------------------------
!<建物>の原画用 XYz XY平面の Z軸移動。
!
!原画_行ベクト
ル
新しい原画_行ベクトル
!
(X,Y,0,1)|1 0 0
0| →(X+(dxdz)*z, Y, z, 1)
! |0 1 0
0|
! |0 0 0
0| dxdz: Z軸カーブの微分 dx/dz
! |(dxdz)*z
0 z
1| z: Z軸 移動差分
MAT READ XYz
DATA 1,0,0,0
DATA 0,1,0,0
DATA 0,0,0,0
DATA 0,0,0,1
!-------------------------------------------------------------------------
!
DEF yaw(z)= 10*SIN((z-2)*0.1) !カーブ、横の偏差 x(z)
DEF d_yaw(z)= COS((z-2)*0.1) !カーブ、微分係数 dx/dz
DEF pitch(z)= 5*SIN(z*0.1) !ピッチ、縦の偏差 y(z)
DEF d_pitch(z)= 0.5*COS(z*0.1) !ピッチ、微分係数 dy/dz
!
DEF v(t)=v0+a*t !速度
DEF I_v(t)=v0*t+a*t*t/2 !移動距離 ∫v(t)dt
!
LET
v0=15
!初速度
LET
a=-v0^2/2/100
!減速加速度, -v0^2/2/移動距離
!
LET
Zs=1.5 !
透視面のz座標( 視点 Z=0)
SET WINDOW -1,1,-1,1 !画面スケール±1
LET t0=TIME
DO
LET t1=TIME-t0
IF t1>tb+0.15 THEN
LET tb=t1
LET
d=I_v(t) !車両前縁d のz座標
PRINT USING "時間=###.## 速度=###.## 走行距離=###.##":t,v(t),d
SET DRAW mode hidden !裏ページに書く
CALL
Animation !
描画
SET DRAW mode explicit !裏ページの表示
LET t=t+.15
END IF
MOUSE POLL msx,msy,mlb,mrb
LOOP UNTIL v(t)<=0 OR mrb=1
SUB Animation
!----sky
SET AREA COLOR 17
PLOT AREA:-1,0; 1,0; 1,1; -1,1
!----ground
SET AREA COLOR 42
PLOT AREA:-1,0; 1,0; 1,-1; -1,-1
!----guide message
SET TEXT COLOR 1
SET TEXT FONT "",11
PLOT TEXT,AT.35,.9:"右クリック保持 Stop"
SET TEXT COLOR 0
SET TEXT FONT "",90
!----
LET ss=5/2
FOR i=IP((d+150)/ss)*ss TO d STEP -ss
LET z=i-d+Zs !視点 Z=0 〜iのz座標。
LET Mp(4,1)= yaw(i)-yaw(d) -1.5 !投影面中心線から道路左端のx座標
LET Mp(4,2)=pitch(i)-pitch(d)-1.5 !投影面中心線から道路左端のy座標
LET Mp(4,4)= z
!----
!
1
,0
,0 ,0|
!
0
,1
,0 ,0|
!
0
,0
,0 ,1|
! yaw(i)-yaw(d)-1.5
,pitch(i)-pitch(d)-1.5
,0 ,z|
!----
IF MOD(i,10)=0 THEN
DRAW Building( 0-2,-9, -3,20,-2 ) WITH Mp !x,y, W,H,D
DRAW Building( 6+2,-9, -3,19, 2.5) WITH Mp !x,y, W,H,D
DRAW Sign WITH Mp
END IF
IF MOD(i,10)=5 THEN DRAW Tree WITH Mp
DRAW Road(-.993*ss) WITH Mp
NEXT i
END SUB
PICTURE Building(x,y,w,h,d1)
IF Zs-z<=w THEN
!---back plane
LET zY(1,1)=d_yaw(i+w/2) !Z軸カーブの微分 dx/dz
LET
zY(4,1)=x+d1
!ZY平面のx座標
DRAW Wall((y),w,h) WITH zY
!---facade
LET
zY(4,1)=x !ZY平面のx座標
DRAW Wall((y),w,h) WITH zY
!---side plane
LET XYz(4,1)=d_yaw(i+w/2)*w !Z軸カーブによるx移動差分
LET
XYz(4,3)=w
!Z軸 移動差分
DRAW Side(x,y,h,d1) WITH XYz
END IF
END PICTURE
!
PICTURE Wall(y,w,h)
SET AREA COLOR 8 !gray
PLOT AREA: 0,y; w,y; w,y+h; 0,y+h !(Z,Y)平面として描く。
FOR y=y+h-.5 TO y+1 STEP -2.5
PLOT LINES: 0,y;
w,y
!(Z,Y)平面として描く。
NEXT y
END PICTURE
!
PICTURE Side(x,y,h,d1)
SET AREA COLOR 16 !dark gray
PLOT AREA: x,y; x+d1,y; x+d1,y+h; x,y+h !移動前(X,Y)平面として描く。
END PICTURE
PICTURE Road(e)
IF e< Zs-z THEN LET e=Zs-z
LET Xz(2,1)=d_yaw(i+e/2) !Z軸カーブの微分 dx/dz
LET Xz(2,2)=d_pitch(i+e/2) !Z軸ピッチの微分 dy/dz
DRAW Surface(e) WITH Xz
END PICTURE
!
PICTURE Surface(e)
IF Mp(4,2)/z<=d_pitch(i+e/2) THEN
SET AREA COLOR 15
PLOT AREA: 0,0; 6,0; 6,e;
0,e
!(X,Z)平面として描く。
!---center line
SET AREA COLOR 0
PLOT AREA: 2.9,0; 2.9,e; 3.1,e; 3.1,0 !(X,Z)平面として描く。
ELSE
!---back side
SET AREA COLOR 2
PLOT AREA: 0,0; 6,0; 6,e;
0,e
!(X,Z)平面として描く。
END IF
!---joint line
PLOT LINES: 0 ,0; 2.9,0
PLOT LINES: 3.1,0; 6 ,0
END PICTURE
PICTURE Tree
SET AREA COLOR 12 !幹
PLOT AREA:-0.075,0; 0.075,0; 0.025,3;-0.025,3
SET AREA COLOR 10
FOR w=1 TO 7 !葉
DRAW disk WITH SCALE(0.3+0.05-RND*0.1)*SHIFT(0.4-RND*0.8, 2.7+0.325-RND*0.75)
NEXT W
END PICTURE
PICTURE Sign
IF MOD(i,50)=0 THEN SET AREA COLOR 2 ELSE SET AREA COLOR 4
PLOT AREA:-0.025,0; 0.025,0; 0.025,2;-0.025,2 !pole
DRAW disk WITH SCALE(0.5)*SHIFT(0,2) !plate
!PLOT TEXT,AT -.35,1.74,USING ">%%":STR$(i) !sign
CALL Plot_7segment(0 ,2 ,0.15 ,STR$(i)) !sign( PLOT TEXT が重い時)
END PICTURE
SUB Plot_7segment(x,y,s,i$) !文字列中心(x,y) 文字の横幅(s) 数字の文字列(i$)
SET LINE COLOR 0
SET LINE width 9/z !一点投影・縮小の補償。(線幅は MAT 文で縮まない)
LET w=LEN(i$)
LET s1=s ! y軸↑:s1=s y軸↓:s1=-s
LET s2=s/2
LET x=x-(w-1)*s2*1.6
FOR p=1 TO w
SELECT CASE VAL(i$(p:p))
CASE 0
PLOT LINES:x-s2,y+s;x-s2,y-s;x+s2,y-s;x+s2,y+s;x-s2,y+s
CASE 1
PLOT LINES:x,y-s;x,y+s
CASE 2
PLOT LINES:x-s2,y+s1;x+s2,y+s1;x+s2,y;x-s2,y;x-s2,y-s1;x+s2,y-s1
CASE 3
PLOT LINES:x-s2,y-s;x+s2,y-s;x+s2,y+s;x-s2,y+s
PLOT LINES:x-s2,y;x+s2,y
CASE 4
PLOT LINES:x-s2,y+s1;x-s2,y;x+s2,y
PLOT LINES:x+s2,y+s1;x+s2,y-s1
CASE 5
PLOT LINES:x+s2,y+s1;x-s2,y+s1;x-s2,y;x+s2,y;x+s2,y-s1;x-s2,y-s1
CASE 6
PLOT LINES:x+s2,y+s1;x-s2,y+s1;x-s2,y-s1;x+s2,y-s1;x+s2,y;x-s2,y
CASE 7
PLOT LINES:x-s2,y+s1;x+s2,y+s1;x+s2,y-s1
CASE 8
PLOT LINES:x-s2,y;x-s2,y-s;x+s2,y-s;x+s2,y+s;x-s2,y+s;x-s2,y;x+s2,y
CASE 9
PLOT LINES:x+s2,y;x-s2,y;x-s2,y+s1;x+s2,y+s1;x+s2,y-s1;x-s2,y-s1
CASE ELSE
END SELECT
LET x=x+s*1.6
NEXT p
SET LINE width 1
SET LINE COLOR 1
END SUB
SET bitmap SIZE 601,601
SET WINDOW -1,21,-1,21 !バウンドを検討する象限を選ぶ
DRAW grid
LET w=5 !テーブル(コート)の大きさ
LET h=4
FOR y=0 TO 5 !縦方向へ鏡面コピー
FOR x=0 TO 4 !横方向
LET cx=x*w+w/2
LET cy=y*h+h/2
DRAW rect WITH SCALE(1-2*MOD(x,2),1-2*MOD(y,2))*SHIFT(cx,cy) !倍率SCALE変換で鏡面コピーする
PLOT TEXT ,AT cx,cy: STR$(ABS(x)+ABS(y)) !バウンドの回数(中央)
PLOT TEXT ,AT x*w+1,y*h+1: STR$(y*(w-1)+x) !テーブル番号(左下)
PLOT TEXT ,AT x*w+0.1,y*h+0.1: mid$("ABCD",MOD(x,2)+2*MOD(y,2)+1,1) !頂点
NEXT x
NEXT y
LET ex=6 !目標の位置
LET ey=11
PLOT LINES: 0,0; ex,ey !上、下、右でバウンドする
!FOR i=1 TO 50-1
! DRAW disk WITH SCALE(0.1)*SHIFT(i*ex/50,i*ey/50)
!NEXT i
PICTURE rect !原点で対称な長方形を描く
PLOT LINES: -w/2,-h/2; w/2,-h/2; w/2,h/2; -w/2,h/2; -w/2,-h/2
DRAW disk WITH SCALE(0.1)*SHIFT(w/2-1,h/2-1) !目標
END PICTURE
END
!曲線上に文字を表示する
SET WINDOW -5,5,-5,5
DRAW grid
SET TEXT HEIGHT 0.5
SET TEXT JUSTIFY "CENTER","BOTTOM"
DRAW TextOnPath("Abcあい漢",1.5) WITH SHIFT(-2,-1)
END
EXTERNAL FUNCTION f(x) !曲線 y=f(x) ※陽関数表示
!LET f=ABS(x-3)
!LET f=x^3
LET f=SIN(x)
END FUNCTION
EXTERNAL PICTURE TextOnPath(s$,L) !曲線上に文字を表示する
IF LEN(s$)=0 OR L<=0 THEN EXIT PICTURE
LET k=1 !k文字目
LET S=0 !曲線y=f(x)の区間[a,b]の長さ S=∫[a,b]SQR(1+f'(x)^2)dx
LET H=0.05
LET i=0
DO
LET t=H*i !リーマン和、区分求積
LET Ft=f(t)
LET df=(f(t+H)-Ft)/H !導関数 f'(x) ※微分係数による
LET S=S+H*SQR(1+df*df)
IF S>=(k-1)*L THEN !文字間隔ごとに
DRAW disk WITH SCALE(0.05)*SHIFT(t,Ft) !位置を印す
SET TEXT ANGLE ANGLE(1,df) !角度を調整する
PLOT TEXT ,AT t,Ft: s$(k:k) !k文字目
LET k=k+1 !次の文字へ
IF k>LEN(s$) THEN EXIT PICTURE !すべての文字を表示したなら
ELSE
PLOT LINES: t,Ft; !曲線の軌跡
END IF
LET i=i+1
LOOP
END PICTURE
●媒介変数表示
!曲線上に文字を表示する
SET WINDOW -5,5,-5,5
DRAW grid
SET TEXT HEIGHT 0.5
SET TEXT JUSTIFY "CENTER","BOTTOM"
DRAW TextOnPath("Abcあい漢",1.5) WITH SHIFT(-2,-1)
END
EXTERNAL FUNCTION x(t) !曲線 x=f(t)、y=f(t) ※媒介変数表示
!!!LET x=t !y=sin(x)
LET x=3*COS(t) !半径3の円
END FUNCTION
EXTERNAL FUNCTION y(t)
!!!LET y=SIN(t) !y=sin(x)
LET y=3*SIN(t) !半径3の円
END FUNCTION
EXTERNAL PICTURE TextOnPath(s$,L) !曲線上に文字を表示する
IF LEN(s$)=0 OR L<=0 THEN EXIT PICTURE
LET k=1 !k文字目
LET S=0 !曲線x=f(t),y=g(t)の区間[a,b]の長さ S=∫[a,b]SQR((dx/dt)^2+(dy/dt)^2)dx
LET H=0.05
LET i=0
DO
LET t=H*i !リーマン和、区分求積
LET Xt=x(t)
LET Yt=y(t)
LET dx=(x(t+H)-Xt)/H !導関数 dx/dt、dy/dt ※微分係数による
LET dy=(y(t+H)-Yt)/H
LET w=dx*dx+dy*dy
LET S=S+H*SQR(w)
IF S>=(k-1)*L THEN !文字間隔ごとに
DRAW disk WITH SCALE(0.05)*SHIFT(Xt,Yt) !位置を印す
IF w<>0 THEN !角度を調整する
SET TEXT ANGLE ANGLE(dx,dy)
ELSE
SET TEXT ANGLE 0
END IF
PLOT TEXT ,AT Xt,Yt: s$(k:k) !k文字目
LET k=k+1 !次の文字へ
IF k>LEN(s$) THEN EXIT PICTURE !すべての文字を表示したなら
ELSE
PLOT LINES: Xt,Yt; !曲線の軌跡
END IF
LET i=i+1
LOOP
END PICTURE
●極座標表示
!曲線上に文字を表示する
SET WINDOW -5,5,-5,5
DRAW grid
SET TEXT HEIGHT 0.5
SET TEXT JUSTIFY "CENTER","BOTTOM"
DRAW TextOnPath("Abcあい漢",3.5) WITH SHIFT(-2,-1)
END
EXTERNAL FUNCTION r(t) !曲線 r=f(θ) ※極座標表示
LET r=3*(1+COS(t))
END FUNCTION
EXTERNAL PICTURE TextOnPath(s$,L) !曲線上に文字を表示する
IF LEN(s$)=0 OR L<=0 THEN EXIT PICTURE
LET k=1 !k文字目
LET S=0 !曲線r=f(θ)の区間[a,b]の長さ S=∫[a,b]SQR(r(θ)^2+r'(θ)^2)dx
LET H=0.05
LET i=0
DO
LET t=H*i !リーマン和、区分求積
LET Rt=r(t)
LET dr=(r(t+H)-Rt)/H !導関数 r'(θ) ※微分係数による
LET w=Rt*Rt+dr*dr
LET S=S+H*SQR(w)
LET x=Rt*COS(t) !極座標(r,θ)→直交座標(x,y)
LET y=Rt*SIN(t)
IF S>=(k-1)*L THEN !文字間隔ごとに
DRAW disk WITH SCALE(0.05)*SHIFT(x,y) !位置を印す
IF w<>0 THEN !角度を調整する
SET TEXT ANGLE ANGLE(dr,Rt)+t
!SET TEXT ANGLE ANGLE(dr-Rt*TAN(t),Rt+dr*TAN(t))
ELSE
SET TEXT ANGLE 0
END IF
PLOT TEXT ,AT x,y: s$(k:k) !k文字目
LET k=k+1 !次の文字へ
IF k>LEN(s$) THEN EXIT PICTURE !すべての文字を表示したなら
ELSE
PLOT LINES: x,y; !曲線の軌跡
END IF
LET i=i+1
LOOP
END PICTURE
!以下の2例で、文字の大きさが 1.5倍、実行速度が200倍ほど違いますが、
!私の環境(Win98SE)だけでしょうか? (Ver.7.4.0 の PLOT TEXT)
!
SET TEXT font "",14
SET TEXT background "OPAQUE"
SET WINDOW -1,1,-1,1
DIM m(4,4)
!
MAT m=IDN
!
LET t0=TIME
FOR i=1 TO 5000
DRAW new_text WITH m
NEXT i
PRINT USING"###.###sec":TIME-t0
!
LET m(1,1)=-1
!
LET t0=TIME
FOR i=1 TO 5000
DRAW new_text WITH m
NEXT i
PRINT USING"###.###sec":TIME-t0
PICTURE new_text
PLOT TEXT,AT 0,0,USING"#####":STR$(i)
END PICTURE
LET t=fnV("1234",10)
PRINT t
LET t=fnV("567",10)
PRINT t
LET s$=fnS$(11,2)
PRINT s$
LET s$=fnS$(14,2)
PRINT s$
END
EXTERNAL FUNCTION fnV(s$,p)
LET L=LEN(s$)
IF L=0 THEN EXIT FUNCTION
LET fnV=fnV(s$(1:L-1),p)*p + VAL(s$(L:L))
END FUNCTION
EXTERNAL FUNCTION fnS$(n,p)
IF n=0 THEN EXIT FUNCTION
LET fnS$=fnS$(INT(n/p),p) & STR$(MOD(n,p))
END FUNCTION
もっと単純な例です。
10 DECLARE EXTERNAL FUNCTION f
20 PRINT f(0)
30 PRINT f(1)
40 PRINT f(0)
50 END
60 EXTERNAL FUNCTION f(x)
70 IF x=0 THEN EXIT FUNCTION
80 LET f=1
90 END FUNCTION
十進BASICを作り始めたころ(たぶん現在配布しているWindows95版まで)は関数定義の戻り値をスタック上に確保していましたが,それでは規格に合わないので,現在のバージョンは静的な変数を用いています。
規格では,「定義関数名に最後に代入された値」となっています。また,定義関数名は文法上,変数ではありません(だから局所変数でもない)。したがって,今回の呼び出しで値を設定しないと,前回設定した値を返すことになります。
最後に定義関数名に代入された値を関数値とするため,
10 DECLARE EXTERNAL FUNCTION f
20 PRINT f(2)
30 END
40 EXTERNAL FUNCTION f(x)
50 LET f=x
60 IF x=2 THEN LET y=f(x-1)
70 END FUNCTION
の実行結果は2でなく1になります。
! 射影変換 sample\transfo9.bas追加
DIM T(4,4)
MAT READ T
DATA 1, 0, 0, -0.25
DATA 0, 1, 0, 0.2
DATA 0, 0, 1, 0
DATA 0, 0, 0, 1
PICTURE House
SET AREA COLOR 15
PLOT AREA: 0, 1; 0, 0; 2, 0; 2, 1 ! 壁
SET AREA COLOR 2
PLOT AREA: -0.6,1; 2.6, 1; 2, 2; 0, 2 ! 屋根
SET AREA COLOR 10
PLOT AREA: 0.1, 0; 0.1,0.8; 0.5,0.8; 0.5, 0 ! ドア
SET AREA COLOR 5
PLOT AREA: 1.4,0.4; 1.9,0.4; 1.9,0.8; 1.4,0.8 ! 窓
SET AREA COLOR 12
PLOT AREA: 1.7, 2; 1.7,2.3; 1.5,2.3; 1.5, 2 ! 煙突
SET TEXT HEIGHT 2 !<----- 大きくするとNG
PLOT TEXT ,AT 0,0: "屋根"
END PICTURE
SET WINDOW -5,5,-5,5
DRAW axes
DRAW House WITH T
END
「常に物理座標」では、これを有効にした表示は正しいのでしょうか?
SET WINDOW -5,5,-5,5
DRAW grid
!2つの消失点
DATA 4,1 !水平線(X軸に平行)の消失点(x1,y1)
DATA -3,4 !垂直線(Y軸に平行)の消失点(x2,y2)
READ x1,y1, x2,y2
DRAW vp WITH SHIFT(x1,y1)
DRAW vp WITH SHIFT(x2,y2)
PICTURE vp !マーカーを描く
LET a=0.125
PLOT AREA: -a,-a; a,-a; a,a; -a,a
END PICTURE
DIM M(4,4) !消失点になるように台形変形する
MAT M=IDN
LET M(1,4)=1/(x1-x2) !消失点(x,0)なら、1/x。 x→∞なら、0
LET M(2,4)=1/(y2-y1) !消失点(0,y)なら、1/y。 y→∞なら、0
DIM Mp(4,4)
MAT Mp=SHIFT(-x2,-y1)*M*SHIFT(x2,y1)
DRAW t WITH Mp
PICTURE t !変形された図形を描く
PLOT LINES: -1,-1; 1,-1; 1,1; -1,1; -1,-1 !境界線を描く
PLOT LINES: -1,0; 1,0 !軸
PLOT LINES: 0,-1; 0,1
SET TEXT HEIGHT 1 !正規座標内の図形 ←←←← ここ
!※「問題座標(JIS)」では、既定値が0.01のため SET TEXT HEIGHT はほぼ必須となる。
PLOT TEXT ,AT 0, 0: "F"
PLOT TEXT ,AT -1, 0: "2"
PLOT TEXT ,AT -1,-1: "@"
PLOT TEXT ,AT 0,-1: "M"
END PICTURE
END
LET Pieces=5 !駒の数
LET Col=5 !盤の短辺の長さ ※5は固定
LET Row=8 !盤の長辺の長さ
LET PieceSize=4 !駒の大きさ
LET MaxSymmetry=8 !駒の置き方の最大数
LET MaxSite=(Col+1)*Row-1
LET LimSite=(Col+1)*(Row+1)
DIM board$(0 TO LimSite-1)
DIM NAME$(0 TO 2-1, 0 TO Pieces-1)
DIM symmetry(0 TO Pieces-1)
DIM shape(0 TO Pieces-1, 0 TO MaxSymmetry-1, 0 TO (PieceSize-1)-1)
DIM REST(0 TO Pieces-1)
LET count=0 !解答数
CALL initialize
CALL try(0)
SUB initialize
local site, piece, state
FOR site=0 TO MaxSite-1 !盤をつくる
IF MOD(site,Col+1)=Col THEN LET board$(site)="*" ELSE LET board$(site)=""
NEXT site
FOR site=MaxSite TO (LimSite-1)-1
LET board$(site)="*"
NEXT site
LET board$(LimSite-1)="" !番人
! ┌─┐Col+1
! * ┐
! * │
! * │
! * │
! * │Row+1
! * │
! * │
! * │← MaxSite-1
! ***** ┘
! ↑ LimSite-1
FOR piece=0 TO Pieces-1 !駒を読み込む
LET REST(piece)=2 !2枚ずつ
READ NAME$(1,piece),NAME$(0,piece), symmetry(piece) !名称、個数
FOR state=0 TO symmetry(piece)-1
FOR site=0 TO (PieceSize-1)-1
READ shape(piece,state,site) !形状
NEXT site
NEXT state
NEXT piece
END SUB
SUB found !解の表示
!!!local i,j
LET count=count+1
PRINT "解";count
FOR i=0 TO Col-1
FOR j=i TO MaxSite-1 STEP Col+1
PRINT board$(j);
NEXT j
PRINT
NEXT i
END SUB
SUB try(site) !再帰的に試みる
local piece,state,s0,s1,s2
LET piece=0
DO WHILE piece<Pieces !未使用の駒に対して
IF REST(piece)=0 THEN
ELSE
LET REST(piece)=REST(piece)-1 !この駒を使用する
LET state=0
DO WHILE state<symmetry(piece) !すべての向きに置いてみる
LET s0=site+shape(piece,state,0)
IF board$(s0)<>"" THEN !ここに四角1が置ければ
ELSE
LET s1=site+shape(piece,state,1)
IF board$(s1)<>"" THEN !四角2
ELSE
LET s2=site+shape(piece,state,2)
IF board$(s2)<>"" THEN !四角3
ELSE
LET board$(site),board$(s0),board$(s1),board$(s2)=NAME$(REST(piece),piece)
LET temp=site !次の空き位置を探す
DO
LET temp=temp+1
LOOP WHILE board$(temp)<>""
IF temp<MaxSite THEN CALL try((temp)) ELSE CALL found
LET board$(site),board$(s0),board$(s1),board$(s2)=""
END IF !continue
END IF
END IF
LET state=state+1
LOOP
LET REST(piece)=REST(piece)+1 !未使用
END IF !continue
LET piece=piece+1
LOOP
END SUB
! tetromin.dat -- テトロミノの駒の形のデータ
!配列borad$()の要素番号と盤上配置との関係
! site
! ↓
! * 1 2 3
! 4 5 6 7 8 9
! 101112131415
! 161718192021
! └ Col+1 ┘ ※Col=5
DATA "O","o", 1 !名称、個数
DATA 1,6,7 !形状 s0,s1,s2
DATA "I","i", 2
DATA 1,2,3
DATA 6,12,18
DATA "T","t", 4
DATA 1,2,7
DATA 5,6,7
DATA 5,6,12
DATA 6,7,12
DATA "Z","z", 4
DATA 1,5,6
DATA 1,7,8
DATA 5,6,11 !裏
DATA 6,7,13
DATA "L","l", 8
DATA 1,2,6
DATA 1,2,8
DATA 1,6,12
DATA 1,7,13
DATA 4,5,6 !裏
DATA 6,7,8
DATA 6,11,12
DATA 6,12,13
END
!投稿(記述例)、情報、アルゴリズム、パズル、移植
! PLOT TEXT 文字の、鏡像テスト。
!
!-------------------
LET N=1 !0,1,2, 通常の万華鏡は2にする。
LET NN=2^N
SET TEXT JUSTIFY "center","half"
SET TEXT BACKGROUND "OPAQUE"
ASK PIXEL SIZE (0,0;1,1) xx,yy
LET xx=xx/2
LET yy=yy/2
SET WINDOW -xx/NN,xx/NN, -yy/NN,yy/NN
LET φ=0
LET stp=-PI/180*6
DO
LET t=INT(TIME)
IF t0<>t THEN
LET t0=t
IF 2*PI<=ABS(φ) THEN LET stp=-stp
LET φ=REMAINDER(φ, 2*PI) +stp
!-----
SET DRAW mode hidden
CLEAR
SET TEXT font "Century",12*NN
DRAW D4(N) WITH SHIFT(-300/2,-300/2/SQR(3))*ROTATE(φ*(-1)^N)*SCALE(1,(-1)^N)
SET TEXT font "Century",12
PLOT TEXT,AT (xx-80)/NN,(yy-10)/NN:"Right Click to Stop"
DRAW center WITH SHIFT(-300/2/NN,-300/2/SQR(3)/NN)*ROTATE(φ)
SET DRAW mode explicit
END IF
WAIT DELAY 0 ! 省電力効果
MOUSE POLL mx,my,mlb,mrb
LOOP UNTIL mrb>=1 ! 右クリックで停止
PICTURE center
SET LINE COLOR 2
SET LINE width 2
PLOT LINES:0,0; 300/NN,0; 300/2/NN,300*SQR(3)/2/NN; 0,0
SET LINE width 1
SET LINE COLOR 1
END PICTURE
!------
PICTURE D4(k)
IF 0< k THEN
DRAW D4(k-1) WITH SCALE(1/2,1/2)*SHIFT(300/4,SQR(3)*300/4) ! 内側の上
DRAW D4(k-1) WITH SCALE(1/2,-1/2)*SHIFT(300/4,SQR(3)*300/4) ! 内側の中
DRAW D4(k-1) WITH SCALE(1/2,1/2)*ROTATE(-PI*2/3)*SHIFT(300/4,SQR(3)*300/4) !内側の左
DRAW D4(k-1) WITH SCALE(1/2,1/2)*ROTATE(PI*2/3)*SHIFT(300,0) ! 内側の右
ELSE
DRAW A_Clock WITH ROTATE(-φ)*SHIFT(300/2,300/2/SQR(3))
PLOT LINES:0,0; 300,0; 300/2,300*SQR(3)/2; 0,0 ! 外側の基準三角形
END IF
END PICTURE
!------
PICTURE A_Clock
SET AREA COLOR 1
FOR i=1 TO 60
LET a=-PI/30*(i-15)
IF MOD(i,5)=0 THEN
PLOT TEXT,AT
60*COS(a)+.5, 60*SIN(a)
:STR$(i/5)
!数字
! CALL Plot_7segment( 60*COS(a) ,60*SIN(a) ,5.5 ,STR$(i/5)) !数字(代替)
END IF
DRAW disk WITH SCALE(1-.5*SGN(MOD(i,5)))*SHIFT(72*COS(a),72*SIN(a)) !分目盛り
NEXT i
!---
DRAW hand(1) WITH SCALE(2.5, 0.75)*ROTATE(-t*PI/21600) !時針
DRAW hand(1) WITH
ROTATE(-t*PI/1800)
!分針
DRAW hand(1) WITH SCALE(0, 1.1)*ROTATE(-t*PI/30) !秒針
DRAW disk WITH
SHIFT(0,0)*SCALE(4)
!中心の飾り
END PICTURE
PICTURE hand(c)
SET AREA COLOR c
PLOT AREA: -1,-15; 1,-15; 1,60; -1,60 !3針共用、0時位置の針
END PICTURE
!--------------------------------------------------------------------------
SUB Plot_7segment(x,y,s,i$) !文字列中心(x,y) 文字の横幅(s) 数字の文字列(i$)
LET w=LEN(i$)
LET s1=s ! y軸↑:s1=s y軸↓:s1=-s
LET s2=s/2
LET x=x-(w-1)*s2*1.6
FOR p=1 TO w
SELECT CASE VAL(i$(p:p))
CASE 0
PLOT LINES:x-s2,y+s;x-s2,y-s;x+s2,y-s;x+s2,y+s;x-s2,y+s
CASE 1
PLOT LINES:x,y-s;x,y+s
CASE 2
PLOT LINES:x-s2,y+s1;x+s2,y+s1;x+s2,y;x-s2,y;x-s2,y-s1;x+s2,y-s1
CASE 3
PLOT LINES:x-s2,y-s;x+s2,y-s;x+s2,y+s;x-s2,y+s
PLOT LINES:x-s2,y;x+s2,y
CASE 4
PLOT LINES:x-s2,y+s1;x-s2,y;x+s2,y
PLOT LINES:x+s2,y+s1;x+s2,y-s1
CASE 5
PLOT LINES:x+s2,y+s1;x-s2,y+s1;x-s2,y;x+s2,y;x+s2,y-s1;x-s2,y-s1
CASE 6
PLOT LINES:x+s2,y+s1;x-s2,y+s1;x-s2,y-s1;x+s2,y-s1;x+s2,y;x-s2,y
CASE 7
PLOT LINES:x-s2,y+s1;x+s2,y+s1;x+s2,y-s1
CASE 8
PLOT LINES:x-s2,y;x-s2,y-s;x+s2,y-s;x+s2,y+s;x-s2,y+s;x-s2,y;x+s2,y
CASE 9
PLOT LINES:x+s2,y;x-s2,y;x-s2,y+s1;x+s2,y+s1;x+s2,y-s1;x-s2,y-s1
CASE ELSE
END SELECT
LET x=x+s*1.6
NEXT p
END SUB
LET si=11 !正三角形(x1,y1)(x2,y2)(x3,y3) の一辺。
LET x1=1.5
LET y1=2.5
!---- !必ずしも、等辺でなくてよいが、外壁表示はズレる。
LET x2=x1+si
LET y2=y1
LET x3=x1+si/2
LET y3=y1+SQR(3)*si/2
!---- !
3
LET A12=(y2-y1)/(x2-x1) ! f13 / \ f23
LET A13=(y3-y1)/(x3-x1) ! 1───2
LET A23=(y3-y2)/(x3-x2) ! f12
DEF f12(x)=A12*(x-x1)+y1 ! ─
DEF f13(x)=A13*(x-x1)+y1 ! /
DEF f23(x)=A23*(x-x2)+y2 ! \
!
!ボール位置(bx,by)の前歴の線 y=my/mx*(x-bx)+by と壁の
!
! 直線f12 y=A12*(x-x1)+y1 との交点の式 A12*(x-x1)+y1=my/mx*(x-bx)+by
! x=(A12*x1-y1-bx*my/mx+by)/(A12-my/mx)
! y=f12(x)
! 直線f13 y=A13*(x-x1)+y1 との交点の式 A13*(x-x1)+y1=my/mx*(x-bx)+by
! x=(A13*x1-y1-bx*my/mx+by)/(A13-my/mx)
! y=f13(x)
! 直線f23 y=A23*(x-x2)+y2 との交点の式 A23*(x-x2)+y2=my/mx*(x-bx)+by
! x=(A23*x2-y2-bx*my/mx+by)/(A23-my/mx)
! y=f23(x)
!
LET px12= (x2-x1)/SQR((y2-y1)^2+(x2-x1)^2)
LET py12= (y2-y1)/SQR((y2-y1)^2+(x2-x1)^2) !直線f12 に平行な、単位ベクトル
LET px13= (x3-x1)/SQR((y3-y1)^2+(x3-x1)^2)
LET py13= (y3-y1)/SQR((y3-y1)^2+(x3-x1)^2) !直線f13 に平行な、単位ベクトル
LET px23= (x3-x2)/SQR((y3-y2)^2+(x3-x2)^2)
LET py23= (y3-y2)/SQR((y3-y2)^2+(x3-x2)^2) !直線f23 に平行な、単位ベクトル
LET ox12= py12
LET oy12=-px12 !直線f12 に垂直な、単位ベクトル
LET ox13= py13
LET oy13=-px13 !直線f13 に垂直な、単位ベクトル
LET ox23= py23
LET oy23=-px23 !直線f23 に垂直な、単位ベクトル
!
LET bx=X1 !ボールの初期位置
LET by=Y1
LET mx=SQR(5)/8 !ボールのX速度、ステップ��X
LET my=SQR(3)/20 !ボールのY速度、ステップ��Y
!
SET WINDOW 0,14, 0,14
! DRAW grid(1,1)
SET DRAW MODE NOTXOR !2度書きで消える NOTXOR モード
LET r=0.7 !ボールの半径
!----
PLOT LINES: x1-r*SQR(3),y1-r; x2+r*SQR(3),y2-r; x3,y3+r*2; x1-r*SQR(3),y1-r !表示壁面
SET LINE COLOR 15 !銀
PLOT LINES: x1,y1; x2,y2; x3,y3; x1,y1 ! 計算壁面
SET LINE COLOR 2 !青
SET AREA COLOR 2 !青
!
PLOT TEXT,AT 10,13: "右クリック:停止"
DO
DRAW disk WITH SCALE(r)*SHIFT(bx,by) !ボールを書く
! SET DRAW mode explicit
WAIT DELAY 0.02 !省電力効果と、速度
! SET DRAW mode hidden
DRAW disk WITH SCALE(r)*SHIFT(bx,by) !ボールだけを消す
PLOT LINES :
bx,by; !
履歴線を(書く・消す)
LET bx=bx+mx
LET by=by+my
IF f23(bx)<=by THEN LET bx23=(A23*x2-y2-bx*my/mx+by)/(A23-my/mx)
IF f13(bx)<=by THEN LET bx13=(A13*x1-y1-bx*my/mx+by)/(A13-my/mx)
IF f12(bx)>=by THEN LET bx12=(A12*x1-y1-bx*my/mx+by)/(A12-my/mx)
!----
IF f23(bx)<=by AND x3<=bx23 AND bx23<=x2 THEN
LET bx=bx23
LET by=f23(bx)
LET wy=(mx*px23+my*py23)*py23-(mx*ox23+my*oy23)*oy23
LET mx=(mx*px23+my*py23)*px23-(mx*ox23+my*oy23)*ox23 !mx,my の、壁に平行成分−壁に垂直成分
LET my=wy
ELSEIF f13(bx)<=by AND x1<=bx13 AND bx13<=x3 THEN
LET bx=bx13
LET by=f13(bx)
LET wy=(mx*px13+my*py13)*py13-(mx*ox13+my*oy13)*oy13
LET mx=(mx*px13+my*py13)*px13-(mx*ox13+my*oy13)*ox13
LET my=wy
ELSEIF f12(bx)>=by AND x1<=bx12 AND bx12<=x2 THEN
LET bx=bx12
LET by=f12(bx)
LET wy=(mx*px12+my*py12)*py12-(mx*ox12+my*oy12)*oy12
LET mx=(mx*px12+my*py12)*px12-(mx*ox12+my*oy12)*ox12
LET my=wy
END IF
MOUSE POLL mox,moy,mlb,mrb
LOOP UNTIL 0< mrb
!散歩コースの探索
PUBLIC NUMERIC N !歩数
LET N=16
DIM d(N),x(0 TO N),y(0 TO N) !各歩数での方向と位置
MAT d=ZER
MAT x=ZER !原点
MAT y=ZER
LET x(1)=1 !1歩目は東へ ※0:東、1:北、2:西、3:南
CALL search(2,d,x,y) !2歩目以降
END
EXTERNAL SUB search(s,d(),x(),y()) !バックトラックで検索する
FOR i=-1 TO 1 STEP 2 !右と左のみ
LET dd=MOD(d(s-1)+i,4) !1つ前を基準にする
LET xx=x(s-1) !現在の位置
LET yy=y(s-1)
SELECT CASE dd !s歩目の移動距離
CASE 0 !E
LET xx=xx+s
CASE 1 !N
LET yy=yy+s
CASE 2 !W
LET xx=xx-s
CASE 3 !S
LET yy=yy-s
CASE ELSE
END SELECT
LET x(s)=xx !進める
LET y(s)=yy
LET d(s)=dd !s歩目の方向
IF s=N THEN !指定の歩数に達したら
IF x(N)=x(0) AND y(N)=y(0) THEN !元の位置に戻ったら
MAT PRINT d;
SET bitmap SIZE 600,600 !作画して交差などを確認する
SET WINDOW -40,40,-40,40
CLEAR
DRAW grid(5,5)
SET LINE width 2
SET TEXT HEIGHT 1.5 !※調整が必要である
SET TEXT JUSTIFY "center","half"
FOR k=1 TO N
SET LINE COLOR 1 !奇数と偶数で色分け
IF MOD(k,2)=0 THEN SET LINE COLOR 4
PLOT LINES: x(k-1),y(k-1); x(k),y(k) !軌跡
PLOT TEXT ,AT (x(k-1)+2*x(k))/3,(y(k-1)+2*y(k))/3: STR$(k)
NEXT k
SET LINE width 1 !restore it
pause !OK?
!INPUT PROMPT "OKかNGを入力してください。": y$
END IF
ELSE
CALL search(s+1,d,x,y) !次へ
END IF
NEXT i
END SUB
!回答、情報、アルゴリズム、パズル
OPTION BASE 0
SET WINDOW -7,7, -7,7
DRAW axes
!----
LET
ma=9 !多角形の 角数
3,4,5,6,7,8,,,,
DIM x(ma),y(ma),A(ma),px(ma),py(ma)
LET r=0.7 !ボールの半径
LET
r0=5.5 !計算で使用の 多角形、外接円の半径
LET r1=r0+r/SIN(PI/2-PI/ma) !ボールの当る 多角形、外接円の半径
!
!LET a0=PI*(1.5-1/ma) !(x1,y1)の角。
LET a0=PI*(1.5-3/ma) !(x1,y1)の1つ手前の角。
FOR i=0 TO ma
LET x(i)=r0*COS(a0)
LET y(i)=r0*SIN(a0)
IF 0< i THEN
SET LINE COLOR "silver"
PLOT LINES: x(i-1),y(i-1); x(i),y(i) !計算壁面
SET LINE COLOR "black"
PLOT LINES: r1/r0*x(i-1),r1/r0*y(i-1); r1/r0*x(i),r1/r0*y(i) !ボール壁面
END IF
LET a0=a0+2*PI/ma
NEXT i
! A3
A4 4 A3
!
3 4──3 5/ \3
! A3 / \ A2
A4│ │A2
A5\ /A2 ・・・
! 1───2 1──2 1─2
!
A1
A1
A1
!
FOR i=1 TO ma
LET j=MOD(i,ma)+1
LET
A(i)=(y(j)-y(i))/(x(j)-x(i))
!直線ij の勾配
LET px(i)=(x(j)-x(i))/SQR((y(j)-y(i))^2+(x(j)-x(i))^2)
LET py(i)=(y(j)-y(i))/SQR((y(j)-y(i))^2+(x(j)-x(i))^2) !直線ij に平行な、単位ベクトル
NEXT i
!
LET a0=ANGLE(x(1),y(1))
LET bx=r0*COS(a0)*0.999 ! ボールの初期位置X
LET by=r0*SIN(a0)*0.999 ! ボールの初期位置Y
LET a0=ANGLE(x(2)-x(1),y(2)-y(1))+SQR(2)*PI/ma/1.1313 !ボールの初期角度
LET m0=.23 !ボールの速さ��
LET mx=m0*COS(a0) !ボールの初期��X
LET my=m0*SIN(a0) !ボールの初期��Y
SUB Cross !各辺への衝突検出と反射
LET ok=0
IF ABS(A(n))< 1 THEN
!---壁の直線(y-y0)=(x-x0)*A ,ボール位置と図中心を結ぶ線 y=x*by/bx の交点(xw,yw)。
LET
xw=(x(n)*A(n)-y(n))/(A(n)-by/bx) !xw
優先
LET yw=(xw-x(n))*A(n)+y(n)
IF 0< xw*bx+yw*by AND
xw^2+yw^2<=bx^2+by^2 THEN !壁の外
!---壁の直線(y-y0)=(x-x0)*A, ボール軌跡線(y-by)=(x-bx)*my/mx の交点(xc,yc)。
LET xc=(x(n)*A(n)-y(n)-bx*my/mx+by)/(A(n)-my/mx) !xc 優先
LET yc=(xc-x(n))*A(n)+y(n)
!---壁の一辺内なら、反射処理
IF (x(n)<=xc AND
xc<=x(MOD(n,ma)+1) OR x(MOD(n,ma)+1)<=xc AND xc<=x(n)) THEN
CALL Mirror
END IF
ELSE
!---壁の直線(y-y0)=(x-x0)*A ,ボール位置と図中心を結ぶ線 y=x*by/bx の交点(xw,yw)。
LET
yw=(y(n)/A(n)-x(n))/(1/A(n)-bx/by) !yw
優先
LET xw=(yw-y(n))/A(n)+x(n)
IF 0< xw*bx+yw*by AND
xw^2+yw^2<=bx^2+by^2 THEN !壁の外
!---壁の直線(y-y0)=(x-x0)*A, ボール軌跡線(y-by)=(x-bx)*my/mx の交点(xc,yc)。
LET yc=(y(n)/A(n)-x(n)-by*mx/my+bx)/(1/A(n)-mx/my) !yc 優先
LET xc=(Yc-y(n))/A(n)+x(n)
!---壁の一辺内なら、反射処理
IF (y(n)<=yc AND
yc<=y(MOD(n,ma)+1) OR y(MOD(n,ma)+1)<=yc AND yc<=y(n)) THEN
CALL Mirror
END IF
END IF
END SUB
SUB Mirror !ベクトル(mx,my)の反射を、同じ(mx,my)に上書。
LET bx=xc !ボールを衝突点に置く
LET
by=yc !
単位ベクトル:壁に平行( px(n), py(n) )
!----
垂直(-py(n), px(n) )
LET wy=(mx*px(n)+my*py(n))*py(n)+(mx*py(n)-my*px(n))*px(n)
LET mx=(mx*px(n)+my*py(n))*px(n)-(mx*py(n)-my*px(n))*py(n)
LET
my=wy
!
内積 *方向 内積 *方向
LET
ok=1 !反射報告 !ball速度ベクトルm= (mx*px+my*py)*p−(mx*ox+my*oy)*o
END
SUB !
平行単位vect.p 垂直単位vect.o
SET LINE COLOR "blue"
SET AREA COLOR "blue"
SET DRAW MODE NOTXOR !2度書きで消える NOTXOR モード
!
PLOT TEXT,AT 3.7, 6.4: "右クリック:停止"
DO
DRAW disk WITH SCALE(r)*SHIFT(bx,by) !ボールを書く
! SET DRAW mode
explicit
!ちらつき防止。| かなりな負荷が、かかります。遅い|
! SET DRAW mode
hidden
!ちらつき防止。| パソコンや省電力なら使わないが良|
WAIT DELAY
0.02 !
省電力効果と、速度
DRAW disk WITH SCALE(r)*SHIFT(bx,by) !ボールだけを消す
PLOT LINES :
bx,by; !
履歴線を(書く・消す)
LET bx=bx+mx
LET by=by+my
!----
FOR n=1 TO ma
CALL Cross !衝突検出と反射
IF ok=1 THEN EXIT FOR
NEXT n
MOUSE POLL mox,moy,mlb,mrb
LOOP UNTIL 0< mrb
LET cEps=1e-13 !精度
DIM t(2) !作業用
SET bitmap SIZE 600,600
SET WINDOW -5,5,-5,5
DRAW grid
LET iter=200 !繰り返し回数
LET M=3 !m角形 ※3以上の整数
DIM Pw(M,4) !壁面の端
!DATA 3,-4, 3, 4 !正方形 始点(x1,y1)、終点(x2,y2)
!DATA 3, 4, -3, 4
!DATA -3, 4, -3,-4
!DATA -3,-4, 3,-4
!MAT READ Pw
!MAT PRINT Pw;
LET R=4 !外接円の半径
FOR i=1 TO M !X軸上の点(R,0)から反時計まわりに頂点を得る
LET th=2*PI*(i-1)/M !始点(x1,y1)
LET Pw(i,1)=R*COS(th)
LET Pw(i,2)=R*SIN(th)
LET th=2*PI*i/M !終点(x2,y2)
LET Pw(i,3)=R*COS(th)
LET Pw(i,4)=R*SIN(th)
NEXT i
MAT PRINT Pw;
DIM w(M,2) !壁面の法線ベクトル
FOR i=1 TO M !線分の方向ベクトルから算出する
LET t(1)=-(Pw(i,4)-Pw(i,2)) !X方向
LET t(2)= Pw(i,3)-Pw(i,1) !Y方向
CALL Vec2Normalize(t,t) !正規化
MAT PRINT t;
LET w(i,1)=t(1)
LET w(i,2)=t(2)
NEXT i
FOR i=1 TO M !壁面を表示する
PLOT LINES: Pw(i,1),Pw(i,2); Pw(i,3),Pw(i,4)
NEXT i
!ボールの軌道 直線p(t)=Pa+t*a
DIM a(2) !ボールの移動方向ベクトル
DATA 1,2
MAT READ a
CALL Vec2Normalize(a,a) !|a|=1
MAT PRINT a;
DIM Pa(2) !ボールの発射位置
DATA 1,0
MAT READ Pa
DIM Pc(2) !衝突位置
DIM aa(2) !反射方向ベクトル
FOR k=1 TO iter !バウンドさせる
CALL CalcCollision(Pc,aa)
MAT PRINT Pc; !debug
PLOT LINES: Pa(1),Pa(2); Pc(1),Pc(2) !軌跡を描く
MAT Pa=Pc !次へ
MAT a=aa
NEXT k
!衝突する平面の法線ベクトルをn、入射方向ベクトルをaとする。
!反射方向ベクトルbは、b=a-2*(a・n)*n
!
!また、平面上の任意の点をPs、入射方向ベクトルaの始点をPaとすると、
!衝突位置Pcは、Pc=Pa+{n・(Ps-Pa)/(a・n)}*a
SUB CalcReflection(a(),n(), b()) !反射ベクトルを計算する
MAT t=(2*DOT(a,n))*n !ベクトルaをベクトルnに射影して、その2倍のベクトル
MAT b=a-t
MAT PRINT b; !debug
END SUB
SUB CalcCollision(Pc(),b()) !壁面との衝突位置と反射方向ベクトルを計算する
DIM n(2),Ps(2),Pe(2)
FOR i=1 TO M
CALL Vec2Set(w(i,1),w(i,2), n) !法線ベクトル
CALL Vec2set(Pw(i,1),Pw(i,2), Ps) !平面上の任意の点
PRINT "壁面=";i !debug
LET an=DOT(a,n) !ベクトルaとベクトルnとのなす角を得る |a||n|cosθ<0
IF an<0 THEN !衝突する壁面の表裏判定
MAT t=Ps-Pa
LET nT=DOT(n,t)
IF nT<0 THEN !壁面との位置関係から
MAT t=(nT/an)*a
MAT Pc=Pa+t !交点
CALL Vec2Set(Pw(i,3),Pw(i,4), Pe) !直線の終点
LET v=InRange(Pc, Ps,Pe)
IF v>=0 AND v<=1 THEN !線分上なら
MAT PRINT Pc; !debug
CALL CalcReflection(a,n, b) !反射方向ベクトル
EXIT SUB !1つ見つかれば
ELSE
PRINT "壁面の延長上で衝突する"
MAT PRINT Pc; !debug
END IF
ELSEIF nT=0 THEN
PRINT "衝突中"
MAT PRINT Pa; !debug
MAT Pc=Pa
CALL CalcReflection(a,n, b) !反射方向ベクトル
EXIT SUB !1つ見つかれば
ELSE
PRINT "衝突しない"
END IF
ELSE
PRINT "衝突しない..."
IF i=M THEN
PRINT "すべての壁面と衝突しません。"
STOP
END IF
END IF
NEXT i
END SUB
!PsとPeを結ぶ線分を延長した直線上の点Pcと線分との位置関係
!0≦t≦1なら、線分上
FUNCTION InRange(Pc(), Ps(),Pe())
DIM t1(2),t2(2)
MAT t1=Pe-Ps
MAT t2=Pc-Ps
IF ABS(t1(1))>=cEps THEN !t1(1)<>0
LET v=t2(1)/t1(1) !X方向の比
ELSE !垂直線
IF ABS(t1(2))>=cEps THEN !t1(2)<>0
LET v=t2(2)/t1(2) !Y方向の比
ELSE !1点
LET v=0
END IF
END IF
LET InRange=v
END FUNCTION
END
!ベクトル
EXTERNAL FUNCTION Vec2Length(a()) !長さ |a|
LET Vec2Length=SQR(a(1)*a(1)+a(2)*a(2))
END FUNCTION
EXTERNAL SUB Vec2Normalize(a(),n()) !正規化 n=a/|a|
LET L=Vec2Length(a)
IF L>0 THEN MAT n=(1/L)*a
END SUB
!その他
EXTERNAL SUB Vec2Set(x,y, v())
LET v(1)=x
LET v(2)=y
END SUB
!ファミコン時代の2D RPGを作る
!マップの構成
! 「正面見下ろし」形式のチップ画像を用意して、タイル状に配置する。
! フィールド、オブジェクトの2層で構成される。
! オブジェクト層が移動可能判定の対象とする。
!チップ画像
! 十進BASICはビットマップ画像を扱うのが苦手のため、ベクトル図形(PLOT文)で描画する。
! X、Yとも−1〜1の範囲の座標で表現して、描画単位はPICTURE文でまとめる。
!
!マップの展開
! 十進BASICの問題座標にマップ全体をDRAW文で描画する。
! フィールド、オブジェクトの順に描画する。
!マップの表示(ビュー)
! SET WINDOWS文でビューを構成して、マップの一部を画面に表示する。
!ビューのスクロール
! PC(Player Character)の「中央固定」で追従する。
!キャラクタの移動
! チップ単位、上下左右の4方向。
! 仮想ゲームパッドからの入力をサポートする。
! 移動キー:カーソルキー
! Aボタン:SPACEキー
! Bボタン:
!マップの定義
DATA 15,12 !マップの大きさ
READ msx,msy !マップ情報を読み込む
DATA 1,1,1,2,2, 2,1,1,1,1, 2,2,2,1,1 !チップ配置情報(フィールド)
DATA 1,1,1,2,2, 2,1,1,1,1, 2,2,2,1,1
DATA 1,1,1,2,2, 2,1,1,1,1, 1,1,1,1,1
DATA 1,1,1,1,2, 1,1,1,1,1, 1,1,1,1,1
DATA 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1
DATA 1,2,2,1,1, 1,1,1,1,1, 1,1,1,1,1
DATA 1,2,2,1,1, 1,2,2,2,1, 1,1,1,1,1
DATA 2,2,1,1,1, 1,2,2,2,1, 3,3,1,1,1
DATA 2,2,1,1,1, 1,2,2,2,1, 3,2,2,1,1
DATA 2,2,2,2,1, 1,1,1,1,1, 3,2,2,1,1
DATA 2,2,2,2,1, 1,1,1,1,1, 3,3,2,1,1
DATA 1,1,1,1,1, 1,1,1,1,1, 3,3,3,1,1
DIM mapFld(msy,msx)
MAT READ mapFld
DATA 0, 0, 0, 0,12, 0, 0, 0, 0,11, 0,12,12, 0, 0 !チップ配置情報(オブジェクト)
DATA 0, 0, 0, 0,12, 0, 0, 0, 0,11, 0, 0,12, 0, 0
DATA 0, 0, 0, 0,12, 0, 0, 0, 0,11, 11, 0, 0, 0, 0
DATA 0, 0, 0, 0, 0, 0, 0, 0,11,11, 0, 0, 0, 0, 0
DATA 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
DATA 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
DATA 0,12,12, 0, 0, 0, 0, 0,12, 0, 0, 0, 0, 0, 0
DATA 0, 0,11,11, 0, 0, 0,21,12, 0, 13,13, 0, 0, 0
DATA 0,12,11,11, 0, 0, 0, 0,12, 0, 13,12, 0, 0, 0
DATA 0,12,12,12, 0, 0, 0, 0, 0, 0, 13,12,12, 0, 0
DATA 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0
DATA 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
DIM mapObj(msy,msx)
MAT READ mapObj
!ゲーム画面の定義
LET GAME_TITLE=1 !タイトル
LET GAME_MOVE=2 !移動
LET GAME_TALK=3 !会話
LET GAME_BATTLE=4 !戦闘
LET gs=GAME_TITLE !タイトル画面から
!ビューポートの定義
LET vsx=15 !ビューポートの大きさ(1/2チップ単位)
LET vsy=15
LET vx=0 !位置(左下。※問題座標)
LET vy=0
!移動方向の定義
LET MOVE_NONE=-1 !なし
LET MOVE_RIGHT=0 !右
LET MOVE_UP=2 !上
LET MOVE_LEFT=4 !左
LET MOVE_DOWN=6 !下
!会話文の定義
DATA "はじめる:Aボタン(SPACEキー)" !#1 ※4行単位
DATA "おわる:ESCキー"
DATA ""
DATA "移動:十字(カーソルキー)、OK:Aボタン"
DATA "" !#2
DATA ""
DATA ""
DATA ""
DATA "コーヒータイム♪" !#3
DATA ""
DATA "「休憩をとったら出発だ!」"
DATA ""
DATA "「残念、ぼくは泳げないんだ。」" !#4
DATA "「飛び越えられないぞ...」"
DATA ""
DATA ""
DATA "" !#5
DATA ""
DATA ""
DATA ""
DIM ms$(4*5)
MAT READ ms$
DATA 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0 !イベント配置情報
DATA 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0
DATA 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0
DATA 0,0,0,0,0, 0,0,0,0,0, 4,0,0,0,0
DATA 0,0,0,0,0, 0,0,0,4,4, 0,0,0,0,0
DATA 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0
DATA 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0
DATA 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0
DATA 0,0,0,0,0, 0,0,3,0,0, 0,0,0,0,0
DATA 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0
DATA 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0
DATA 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0
DIM mapEvt(msy,msx)
MAT READ mapEvt
LET evt=0
!ゲームの初期化
LET x=6 !キャラクタの位置(チップ単位)
LET y=5
LET d=MOVE_DOWN !向き
CALL SetViewPort !ビューポート移動
LET t0=TIME
LET fRun=-1 !ゲーム開始
DO WHILE fRun<0 !ゲームループ
IF gs=GAME_TITLE THEN !タイトル画面なら
SET DRAW mode hidden !ちらつき防止(開始)
CLEAR
DRAW Hiro(6,d) WITH SHIFT(vx+8,vy+8) !キャラクタ
PLOT TEXT ,AT vx+6,vy+11: "チョコボの冒険"
CALL DrawSpeak(0,0)
SET DRAW mode explicit !ちらつき防止(終了)
CALL GetAButton(t0) !Aボタンの入力
END IF
IF gs=GAME_MOVE THEN !移動画面なら
CALL GetMoveKey(dx,dy,dr,t0) !移動キーの入力
IF dx<>0 OR dy<>0 THEN !移動なら
LET d=dr !移動方向に向く
LET xx=x+dx !仮に移動する(チップ単位)
LET yy=y+dy
IF xx>0 AND xx<=msx AND yy>0 AND yy<=msy THEN !マップ内で
IF mapObj(yy,xx)=0 THEN !障害物がなければ
LET x=xx !実際に移動させる
LET y=yy
END IF
END IF
CALL SetViewPort !ビューポート移動
LET evt=CheckEvent(mapEvt,x,y) !フィールド上のイベントを確認
END IF
CALL DrawView !ビュー表示
END IF
IF gs=GAME_TALK THEN !会話画面なら
CALL DrawView !ビュー表示
CALL GetAButton(t0) !Aボタンの入力
END IF
IF GetKeyState(27)<0 THEN LET fRun=0 !ESCキーで終了
LOOP
SUB GetMoveKey(dx,dy,dr,t0) !移動キーの入力を確認する
LET dx=0 !移動量
LET dy=0
LET dr=MOVE_NONE !移動方向
IF TIME-t0>0.2 THEN !200ミリ秒ごとに
IF GetKeyState(37)<0 THEN !いずれか1つのみ
LET dx=-1
LET dr=MOVE_LEFT !左カーソルキー
ELSE
IF GetKeyState(38)<0 THEN
LET dy=-1
LET dr=MOVE_UP !上
ELSE
IF GetKeyState(39)<0 THEN
LET dx=1
LET dr=MOVE_RIGHT !右
ELSE
IF GetKeyState(40)<0 THEN
LET dy=1
LET dr=MOVE_DOWN !下
END IF
END IF
END IF
END IF
LET t0=TIME !次へ
END IF
END SUB
SUB GetAButton(t0) !Aボタンの入力を確認する
IF TIME-t0>0.2 THEN !200ミリ秒ごとに
IF GetKeyState(32)<0 THEN LET gs=GAME_MOVE !SPACEキー
LET t0=TIME !次へ
END IF
END SUB
SUB SetViewPort !ビューポートの設定する
LET vx=2*x-vsx/2-1 !「キャラクタの中央固定」でビューポートを追従させる
LET vy=2*(msy-y)-vsy/2+1
SET WINDOW vx,vx+vsx,vy,vy+vsy
END SUB
SUB DrawView !マップ、キャラクタを表示する
SET DRAW mode hidden !ちらつき防止(開始)
CLEAR
CALL DrawLayer(mapFld,msx,msy) !フィールド
CALL DrawLayer(mapObj,msx,msy) !オブジェクト
DRAW Hiro(6,d) WITH SHIFT(2*x-1,2*(msy-y)+1) !キャラクタ
IF gs=GAME_TALK THEN CALL DrawSpeak(evt,0) !会話文
SET DRAW mode explicit !ちらつき防止(終了)
END SUB
SUB DrawSpeak(n,v) !会話文を表示する
SET AREA COLOR 199 !ふきだし
PLOT AREA: vx+1,vy+1; vx+vsx-1,vy+1; vx+vsx-1,vy+5; vx+1,vy+5
SET LINE COLOR 1
SET LINE width 3
PLOT LINES: vx+1,vy+1; vx+vsx-1,vy+1; vx+vsx-1,vy+5; vx+1,vy+5; vx+1,vy+1
SET TEXT HEIGHT 0.4
FOR i=1 TO 4 !4行単位
PLOT TEXT ,AT vx+2,vy+4.75-i*0.75: ms$(n+i)
NEXT i
END SUB
FUNCTION CheckEvent(e(,),x,y) !フィールド上のイベントを確認する
LET a=e(y,x)
IF a>0 THEN LET gs=GAME_TALK !会話画面へ
LET CheckEvent=4*(a-1)
END FUNCTION
END
EXTERNAL SUB DrawLayer(m(,),sx,sy) !レイヤを表示する
FOR j=1 TO sy !奥から順に(正面見下ろし)
LET y=2*(sy-j)+1 !左上を原点、右方向がX軸の正、下方向がY軸の正
FOR i=1 TO sx
LET x=2*i-1
DRAW PutChip(m(j,i)) WITH SHIFT(x,y) !チップ情報をもとに配置する
NEXT i
NEXT j
END SUB
EXTERNAL PICTURE PutChip(i) !番号に対応したチップ画像を描く
IF i=1 THEN DRAW Ground
IF i=2 THEN DRAW Grass
IF i=3 THEN DRAW Rock
IF i=11 THEN DRAW Pool
IF i=12 THEN DRAW Tree
IF i=13 THEN DRAW Mount
IF i=21 THEN DRAW House
END PICTURE
!※作成基準 - X、Y座標とも範囲は-1〜1とする。少しはみ出てもよい。
!キャラクタ
EXTERNAL PICTURE Hiro(c,d) !チョコボ
SET AREA COLOR 8
DRAW disk WITH SCALE(0.8,0.2)*SHIFT(0,-0.9) !影
SET LINE width 2
SET LINE COLOR 1
PLOT LINES: -0.2,-0.3; -0.3,-0.9; -0.1,-0.9 !足
SET AREA COLOR c
DRAW disk WITH SCALE(0.6) !体
PLOT LINES: 0.3,-0.3; 0.4,-0.9; 0.6,-0.8 !足
DRAW disk WITH SCALE(0.45)*SHIFT(0.4,0.4) !頭
SET AREA COLOR 2
PLOT AREA: 0.7,0.5; 1,0.7; 0.7,0.7 !くちばし
SET AREA COLOR 1
DRAW disk WITH SCALE(0.08)*SHIFT(0.5,0.7) !目
END PICTURE
!フィールド
EXTERNAL PICTURE Ground !平地
SET AREA COLOR 27
PLOT AREA: -1,-1; 1,-1; 1,1; -1,1
END PICTURE
EXTERNAL PICTURE Grass !草地
SET AREA COLOR 3
PLOT AREA: -1,-1; 1,-1; 1,1; -1,1
END PICTURE
EXTERNAL PICTURE Rock !岩地
SET AREA COLOR 50
PLOT AREA: -1,-1; 1,-1; 1,1; -1,1
END PICTURE
!オブジェクト
EXTERNAL PICTURE Tree !木
SET AREA COLOR 10
DRAW disk WITH SCALE(0.5)*SHIFT(0,0.5) !葉
DRAW disk WITH SCALE(0.5)*SHIFT(-0.4,0) !葉
DRAW disk WITH SCALE(0.4)*SHIFT(0.5,-0.2) !葉
SET AREA COLOR 12
PLOT AREA: -0.2,-1; 0.2,-1; 0,0 !幹
END PICTURE
EXTERNAL PICTURE Pool !池
SET AREA COLOR 5
PLOT AREA: -1,-1; 1,-1; 1,1; -1,1
END PICTURE
EXTERNAL PICTURE Mount !山
SET AREA COLOR 240
PLOT AREA: -0.6,-1; 1,-1; 0.2,1
PLOT AREA: -1,-1; 0,-1; -0.5,0
END PICTURE
EXTERNAL PICTURE House !家
SET AREA COLOR 15
PLOT AREA: -1,0; -1,-1; 1,-1; 1,0 !壁
SET AREA COLOR 2
PLOT AREA: -1.6,0; 1.6,0; 1,1; -1,1 !屋根
SET AREA COLOR 10
PLOT AREA: -0.9,-1; -0.9,-0.2; -0.5,-0.2; -0.5,-1 !ドア
SET AREA COLOR 5
PLOT AREA: 0.4,-0.6; 0.9,-0.6; 0.9,-0.2; 0.4,-0.2 !窓
SET AREA COLOR 12
PLOT AREA: 0.7,1; 0.7,1.3; 0.5,1.3; 0.5,1 !煙突
END PICTURE
!ベクトルによる平面幾何の計算 - 点、直線(線分)
LET cEps=1e-13 !精度
!ベクトル(a1,a2)とベクトル(b1,b2)との演算
DEF fnDot(a1,a2, b1,b2)=a1*b1+a2*b2 !内積
DEF fnCross(a1,a2, b1,b2)=fnDot(-a2,a1,b1,b2) !擬似外積、パープ内積 a1*b2-a2*b1
DEF fnABS(a,b)=SQR(a*a+b*b) !絶対値、大きさ
DIM a(2),b(2),c(2),d(2) !点A、B、C、D
DATA 4, 4 !A
DATA -1, 1 !B
DATA -3, 2 !C
DATA 3,-4 !D
MAT READ A
MAT READ B
MAT READ C
MAT READ D
SET WINDOW -5,5,-5,5 !グラフを描く
DRAW grid
SET TEXT HEIGHT 0.4
PLOT LINES: A(1),A(2); B(1),B(2) !線分AB
PLOT TEXT ,AT A(1),A(2): "A"
PLOT TEXT ,AT B(1),B(2): "B"
PLOT LINES: C(1),C(2); D(1),D(2) !線分CD
PLOT TEXT ,AT C(1),C(2): "C"
PLOT TEXT ,AT D(1),D(2): "D"
DIM s(2),t(2),u(2),v(2) !作業用
!点Aと点Bを通る直線と点Cと点Dを通る直線との直交・平行判定
!内積が0なら、直交。 外積が0なら、平行。
MAT s=b-a
MAT t=d-c
IF fnDot(s(1),s(2),t(1),t(2))=0 THEN PRINT "直交"
IF fnCross(s(1),s(2),t(1),t(2))=0 THEN PRINT "平行"
!点Aと点Bを通る直線と点Cと点Dを通る直線との交点
MAT s=b-a
MAT t=d-c
LET DD=fnCross(t(1),t(2),s(1),s(2))
IF DD<>0 THEN
MAT u=c-a
MAT v=( fnCross(t(1),t(2),u(1),u(2))/DD ) * s
MAT v=a+v
MAT PRINT v; !交点
ELSE
PRINT "平行です。"
END IF
!点Aと点Bを結ぶ線分と点Cと点Dを結ぶ線分との交点
MAT s=b-a
MAT t=c-a
LET d1=fnCross(s(1),s(2),t(1),t(2))
!MAT s=b-a
MAT t=d-a
LET d2=fnCross(s(1),s(2),t(1),t(2))
MAT s=d-c
MAT t=a-c
LET d3=fnCross(s(1),s(2),t(1),t(2))
!MAT s=d-c
MAT t=b-c
LET d4=fnCross(s(1),s(2),t(1),t(2))
IF d1*d2<=0 AND d3*d4<=0 THEN
MAT u=b-a
MAT u=( ABS(d3)/(ABS(d3)+ABS(d4)) ) * u
MAT u=a+u
MAT PRINT u; !交点
ELSE
PRINT "交差なし"
END IF
!点Cと、点Aと点Bを通る直線との位置関係
MAT s=b-a
MAT t=c-a
LET DD=fnCross(s(1),s(2),t(1),t(2))
IF DD=0 THEN
PRINT "線上"
ELSEIF DD>0 THEN
PRINT "左側"
ELSE
PRINT "右側"
END IF
!点Cが、点Aと点Bを結ぶ線分上にあるかどうかの判定
!三角不等式 |a-b|≦|a-c|+|c-b|
MAT s=a-c
MAT t=c-b
MAT u=a-b
IF fnABS(s(1),s(2))+fnAbs(t(1),t(2))<fnABS(u(1),u(2))+cEps THEN PRINT "線上"
!点Cと、点Aと点Bを通る直線との距離
MAT s=b-a
MAT t=c-a
PRINT ABS(fnCross(s(1),s(2),t(1),t(2))) / fnABS(s(1),s(2))
!点Cと、点Aと点Bを結ぶ線分との距離(最近接点)
MAT s=b-a
MAT t=c-a
MAT u=c-b
IF fnDot(s(1),s(2),t(1),t(2))<cEps THEN !点A外側
PRINT fnABS(t(1),t(2)) !点Aとの距離
ELSEIF fnDot(-s(1),-s(2),u(1),u(2))<cEps THEN !点B外側
PRINT fnABS(u(1),u(2)) !点Bとの距離
ELSE !線分AB内
PRINT ABS(fnCross(s(1),s(2),u(1),u(2))) / fnABS(s(1),s(2)) !垂線
END IF
END
!投稿(記述例)、数学、ベクトルと図形方程式、アルゴリズム、ゲーム、当たり判定
!3×3魔方陣で3段階になるものを検索する
OPTION ARITHMETIC NATIVE !CPUパワー
DIM nm$(0 TO 19) !0〜19
DATA "Zero" !0
DATA "One" !1
DATA "Two" !2
DATA "Three" !3
DATA "Four" !4
DATA "Five" !5
DATA "Six" !6
DATA "Seven" !7
DATA "Eight" !8
DATA "Nine" !9
DATA "Ten" !10
DATA "Eleven" !11
DATA "Twelve" !12
DATA "Thirteen" !13
DATA "Fourteen" !14
DATA "Fifteen" !15
DATA "Sixteen" !16
DATA "Seventeen" !17
DATA "Eighteen" !18
DATA "Nineteen" !19
MAT READ nm$
DIM nm2$(2 TO 9) !20以上
DATA "Twenty" !20
DATA "Thirty" !30
DATA "Fourty" !40
DATA "Fifty" !50
DATA "Sixty" !60
DATA "Seventy" !70
DATA "Eigthy" !80
DATA "Ninety" !90
MAT READ nm2$
FUNCTION f(x) !数値を英語読みに変換する ※0〜999
LET v=0
IF x>=100 THEN LET v=LEN(nm$(INT(x/100))) + LEN("hundred") !百の位
LET xx=MOD(x,100) !0〜99の部分
IF xx<>0 THEN
IF xx<20 THEN !0〜19なら
LET v=v+LEN(nm$(xx))
ELSE
LET v=v+LEN(nm2$(INT(xx/10))) !十の位
LET w=MOD(xx,10) !一の位
IF w<>0 THEN LET v=v+LEN(nm$(w))
END IF
END IF
LET f=v
END FUNCTION
!------------------------------
DIM M(9) !3×3基本形
!DATA 2,9,4 !合計は、15
!DATA 7,5,3
!DATA 6,1,8
!MAT READ M
MAT M=ZER
! M+a*A+b*B+c*C による変形 合計は、15+3*a となる。
DIM A(9)
DATA +1,+1,+1
DATA +1,+1,+1
DATA +1,+1,+1
MAT READ A
DIM B(9)
DATA 0,-1,+1
DATA +1, 0,-1
DATA -1,+1, 0
MAT READ B
DIM C(9) !※Bを90°回転
DATA +1,-1, 0
DATA -1, 0,+1
DATA 0,+1,-1
MAT READ C
LET cTRUE=-1 !真
LET cFALSE=0 !偽
FUNCTION CheckRange(T()) !1〜999
LET CheckRange=cFALSE
FOR i=1 TO 9
IF T(i)<0 OR T(i)>999 THEN EXIT FUNCTION
NEXT i
LET CheckRange=cTRUE
END FUNCTION
FUNCTION CheckUnique(T()) !同じ数字かどうか
LET CheckUnique=cFALSE
FOR i=1 TO 8
FOR j=i+1 TO 9
IF T(i)=T(j) THEN EXIT FUNCTION
NEXT j
NEXT i
LET CheckUnique=cTRUE
END FUNCTION
FUNCTION CheckSum(T()) !合計
LET CheckSum=cFALSE
LET v=3*T(5)
IF v<>T(1)+T(2)+T(3) THEN EXIT FUNCTION !横
IF v<>T(4)+T(5)+T(6) THEN EXIT FUNCTION
IF v<>T(7)+T(8)+T(9) THEN EXIT FUNCTION
IF v<>T(1)+T(4)+T(7) THEN EXIT FUNCTION !縦
IF v<>T(2)+T(5)+T(8) THEN EXIT FUNCTION
IF v<>T(3)+T(6)+T(9) THEN EXIT FUNCTION
IF v<>T(1)+T(5)+T(9) THEN EXIT FUNCTION !斜め
IF v<>T(3)+T(5)+T(7) THEN EXIT FUNCTION
LET CheckSum=cTRUE
END FUNCTION
!------------------------------
DIM T(9),TT(9)
!FOR aa=111 TO 0 STEP -1
FOR aa=0 TO 111 !※
DIM Ta(9)
MAT TT=aa*A
MAT Ta=M+TT
PRINT "合計=";3*M(5)+3*aa; aa
FOR bb=0-Ta(8) TO 999-Ta(8) !※
DIM Tb(9)
MAT TT=bb*B
MAT Tb=Ta+TT
FOR cc=0-Ta(8) TO 999-Ta(8) !※
MAT TT=cc*C
MAT T=Tb+TT !1段階目
!IF CheckRange(T)=cTRUE AND CheckUnique(T)=cTRUE THEN !重複なし
IF CheckRange(T)=cTRUE THEN !重複あり
DIM T1(9)
MAT T1=T !save it
FOR i=1 TO 9 !2段階目
LET T(i)=f(T(i))
NEXT i
!IF CheckUnique(T)=cTRUE AND CheckSum(T)=cTRUE THEN
IF CheckSum(T)=cTRUE THEN
DIM T2(9)
MAT T2=T !save it
!!!MAT PRINT T; !debug
FOR i=1 TO 9 !3段階目
LET T(i)=f(T(i))
NEXT i
!IF CheckUnique(T)=cTRUE AND CheckSum(T)=cTRUE THEN
IF CheckSum(T)=cTRUE THEN
MAT PRINT T1;T2;T; !魔方陣を表示する
PRINT
END IF
END IF
END IF
NEXT cc
NEXT bb
NEXT aa
END
!散歩コースの探索
DECLARE EXTERNAL FUNCTION F.F$ !外部関数の宣言
DECLARE EXTERNAL FUNCTION F2$ !外部関数の宣言
LET t0=TIME
PUBLIC NUMERIC ANSWER_COUNT !解答数
LET ANSWER_COUNT=0
PUBLIC NUMERIC N !歩数
LET N=16
PUBLIC NUMERIC M !マップの大きさ
LET M1=0
LET M2=0
FOR i=0 TO N !※2+4+6+ … +(N-2)+Nより大きく
LET t=LEN(F$(i)) !歩数
!!!LET t=LEN(F2$(i)) !歩数 ←←←←←
IF MOD(i,2)=1 THEN
LET M1=M1+t
ELSE
LET M2=M2+t
END IF
NEXT i
LET M=MAX(M1,M2)
PRINT M;M1;M2
DIM map(-M TO M,-M TO M) !散歩したコース(足跡)
MAT map=(ORD("."))*CON !未踏
LET x=0 !現在位置
LET y=0
!※1歩目と2歩目を固定して、回転と鏡面を排除する
CALL walk(F$(0),map,0,x,y, ok) !1歩目は東へ ※0:東、1:北、2:西、3:南
!!!CALL walk(F2$(1),map,0,x,y, ok) !1歩目は東へ ※0:東、1:北、2:西、3:南 ←←←←←
LET d=MOD(0-1,4) !進行方向
CALL walk(F$(1),map,d,x,y, ok) !2歩目は北へ
!!!CALL walk(F2$(2),map,d,x,y, ok) !2歩目は北へ ←←←←←
CALL search(3,map,d,x,y) !3歩目以降
IF ANSWER_COUNT=0 THEN PRINT "解答なし"
PRINT "計算時間=";time-t0
END
EXTERNAL SUB walk(s$,map(,),d,x,y, ok) !コースに足跡を残す
LET ok=0
LET L=LEN(s$)
SELECT CASE d !進行方向に応じて
CASE 0 !E
FOR i=1 TO L
IF map(y,x+i)<>ORD(".") THEN EXIT SUB !未踏以外なら
LET map(y,x+i)=ORD(s$(i:i))
NEXT i
LET x=x+L !移動先
CASE 1 !N
FOR i=1 TO L
IF map(y+i,x)<>ORD(".") THEN EXIT SUB !未踏以外なら
LET map(y+i,x)=ORD(s$(i:i))
NEXT i
LET y=y+L !移動先
CASE 2 !W
LET x=x-L !移動先 ※予め先に
FOR i=1 TO L
IF map(y,x+i-1)<>ORD(".") THEN EXIT SUB !未踏以外なら
LET map(y,x+i-1)=ORD(s$(i:i))
NEXT i
CASE 3 !S
LET y=y-L !移動先 ※予め先に
FOR i=1 TO L
IF map(y+i-1,x)<>ORD(".") THEN EXIT SUB !未踏以外なら
LET map(y+i-1,x)=ORD(s$(i:i))
NEXT i
CASE ELSE
END SELECT
LET ok=1 !成功
END SUB
EXTERNAL SUB search(s,map(,),d,x,y) !バックトラックで検索する
DECLARE EXTERNAL FUNCTION F.F$ !外部関数の宣言
DECLARE EXTERNAL FUNCTION F2$ !外部関数の宣言
LET s$=F$(s-1) !歩数を算出する
!!!LET s$=F2$(s) !歩数を算出する ←←←←←
LET L=LEN(s$)
DIM mmm(-L TO L) !save map
IF MOD(s,2)=0 THEN
FOR i=-L TO L !1列分のみ(メモリ使用の節約)
LET mmm(i)=map(y+i,x)
NEXT i
ELSE
FOR i=-L TO L !1行分のみ
LET mmm(i)=map(y,x+i)
NEXT i
END IF
FOR k=-1 TO 1 STEP 2 !右と左のみ
LET dd=MOD(d+k,4) !1つ前を基準にして、s歩目の方向を決める
LET xx=x
LET yy=y
CALL walk(s$,map,dd,xx,yy, ok) !s歩目の移動
IF ok=1 THEN
IF s=N THEN !指定の歩数に達したら
IF xx=0 AND yy=0 THEN !元の位置に戻ったら
LET ANSWER_COUNT=ANSWER_COUNT+1 !解答数
PRINT ANSWER_COUNT
FOR i=-M TO M !コースを表示する
LET t$=""
FOR j=-M TO M
LET t$=t$ & CHR$(map(i,j))
NEXT j
PRINT t$ !1行分をまとめて出力する(高速)
NEXT i
PRINT
END IF
ELSE
CALL search(s+1,map,dd,xx,yy) !次へ
END IF
END IF
IF MOD(s,2)=0 THEN !restore map
FOR i=-L TO L
LET map(y+i,x)=mmm(i)
NEXT i
ELSE
FOR i=-L TO L
LET map(y,x+i)=mmm(i)
NEXT i
END IF
NEXT k
END SUB
MODULE F !英語読みに変換する
SHARE STRING nm$(0 TO 19) !0〜19
DATA "Zero" !0
DATA "One" !1
DATA "Two" !2
DATA "Three" !3
DATA "Four" !4
DATA "Five" !5
DATA "Six" !6
DATA "Seven" !7
DATA "Eight" !8
DATA "Nine" !9
DATA "Ten" !10
DATA "Eleven" !11
DATA "Twelve" !12
DATA "Thirteen" !13
DATA "Fourteen" !14
DATA "Fifteen" !15
DATA "Sixteen" !16
DATA "Seventeen" !17
DATA "Eighteen" !18
DATA "Nineteen" !19
MAT READ nm$
SHARE STRING nm2$(2 TO 9) !20以上
DATA "Twenty" !20
DATA "Thirty" !30
DATA "Fourty" !40
DATA "Fifty" !50
DATA "Sixty" !60
DATA "Seventy" !70
DATA "Eigthy" !80
DATA "Ninety" !90
MAT READ nm2$
PUBLIC FUNCTION F$
EXTERNAL FUNCTION F$(x) !数値を英語読みに変換する ※0〜99
IF x<20 THEN !0〜19なら
LET v$=v$ & nm$(x)
ELSE
LET v$=v$ & nm2$(INT(x/10)) !十の位
LET w=MOD(x,10) !一の位
IF w<>0 THEN LET v$=v$ & "-" & nm$(w)
END IF
LET F$=v$
END FUNCTION
END MODULE
EXTERNAL FUNCTION F2$(x) !数値の長さ
LET F2$=REPEAT$(mid$("123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",x,1),x)
END FUNCTION
!回答、情報、アルゴリズム、パズル
LET t0=TIME
LET N=24 !位数
LET w=INT((N-1)/2)+1 !概算
DIM A(w) !1〜nまでの奇数列、偶数列
LET m=0
FOR i=1 TO N
IF MOD(i,2)=1 THEN !奇数なら
!IF MOD(i,2)=0 THEN !偶数なら ←←←←←
LET m=m+1
LET A(m)=i
END IF
NEXT i
redim A(m)
LET ANSWER_COUNT=0
DIM B(m)
FOR i=0 TO 2^(m-1)-1 !ビットパターンで検証する ※MSB=0
MAT B=CON
LET t$=right$(REPEAT$("0",m)&BSTR$(i,2),m) !m桁
FOR k=1 TO LEN(t$)
IF t$(k:k)="1" THEN LET B(k)=-1 !0:1、1:-1へ
NEXT k
IF DOT(A,B)=0 THEN !±1*1 + ±1*3 + … + ±1*(2*m+1)を計算する
LET ANSWER_COUNT=ANSWER_COUNT+1
!!!PRINT "DATA ";CHR$(34);t$;CHR$(34)
END IF
NEXT i
PRINT "個数=";ANSWER_COUNT !奇数の個数
PRINT
PRINT "計算時間=";TIME-t0
END
LET
m_=15 !最大角数
LET
ma=3
!開始角数
LET
m0=.23
!ボールの速さ��
DIM x(m_+1),y(m_+1),A(m_+1),ox(m_+1),oy(m_+1)
SET WINDOW -7,7, -7,7
SET DRAW MODE NOTXOR !2度書きで消える NOTXOR モード
LET
r=0.7 !ボールの半径
LET
r0=5.5
!計算で使用の 多角形、外接円の半径
DO
CLEAR
DRAW axes
LET r1=r0+r/SIN(PI/2-PI/ma) !ボールの当る 多角形、外接円の半径
LET a0=PI*(1.5-1/ma) !(x1,y1)の角。
FOR i=1 TO ma+1
LET x(i)=r0*COS(a0)
LET y(i)=r0*SIN(a0)
IF 1< i THEN
SET LINE COLOR "silver"
PLOT LINES: x(i-1),y(i-1); x(i),y(i) !計算外壁
SET LINE COLOR "black"
PLOT LINES: r1/r0*x(i-1),r1/r0*y(i-1); r1/r0*x(i),r1/r0*y(i) !ボール外壁
END IF
LET a0=a0+2*PI/ma
NEXT i
! A3
A4 4 A3
!
3 4──3 5/ \3
! A3 / \ A2
A4│ │A2
A5\ /A2 ・・・
! 1───2 1──2 1─2
!
A1
A1
A1
!
FOR i=1 TO ma
LET A(i)=(y(i+1)-y(i))/(x(i+1)-x(i)) !直線i~i+1 の勾配
LET oy(i)= (x(i+1)-x(i))/SQR((y(i+1)-y(i))^2+(x(i+1)-x(i))^2)
LET ox(i)=-(y(i+1)-y(i))/SQR((y(i+1)-y(i))^2+(x(i+1)-x(i))^2)
NEXT
i
!直線i~i+1 に垂直な単位ベクトル(左回転)
CALL play00
LET ma=MOD(ma-2,m_-2)+3 !次々角数 3,4,5,6,,,3,4,,
LOOP UNTIL 0< mrb
SUB play00
PLOT TEXT,AT -6.7, 6.4: "左クリック:角数の選択= "& STR$(ma)
PLOT TEXT,AT 3.2, 6.4: "右クリック:停止"
LET i=ANGLE(x(2)-x(1),y(2)-y(1))+SQR(2)*PI/ma/1.1313 !ボールの初期角度
LET
mx=m0*COS(i)
!ボールの初期��X
LET
my=m0*SIN(i)
!ボールの初期��Y
LET i=ANGLE(x(1),y(1))
LET bx=r0*COS(i)*0.999 !ボールの初期位置X
LET by=r0*SIN(i)*0.999 !ボールの初期位置Y
LET nb=0
DO
DRAW disk WITH SCALE(r)*SHIFT(bx,by) !ボールを書く
WAIT DELAY
0.02 !
省電力効果と、速度
DRAW disk WITH SCALE(r)*SHIFT(bx,by) !ボールだけを消す
PLOT LINES :
bx,by; !
履歴線を(書く・消す)
LET bx=bx+mx
LET by=by+my
FOR n=1 TO ma
IF n<>nb THEN
CALL
Sensor !
辺の内外検出と反射(同じ辺の呼出抑制)
IF n=nb THEN EXIT FOR
END IF
NEXT n
IF mlbk=0 OR mlb=0 THEN LET mlbk=2*mlb ELSE LET mlbk=mlbk-1.001/13
MOUSE POLL mox,moy,mlb,mrb
LOOP UNTIL 0< mrb OR mlbk<
mlb !左クリックは、Leading
Edge 検出
PLOT
LINES !do〜loop13
回でオートリピートへ入る
END SUB
SUB Sensor
IF ABS(A(n))< 1 THEN !境界勾配1
LET xc=(x(n)*A(n)-y(n)-bx*my/mx+by)/(A(n)-my/mx) !交点 xc 優先< 45°
LET yc=(xc-x(n))*A(n)+y(n)
IF SGN(yc-by)<>SGN(my) AND SGN(x(n)-xc)<>SGN(x(n+1)-xc) THEN CALL Mirror
ELSE
LET yc=(y(n)/A(n)-x(n)-by*mx/my+bx)/(1/A(n)-mx/my) !交点 yc 優先 >=45°
LET xc=(yc-y(n))/A(n)+x(n)
IF SGN(xc-bx)<>SGN(mx) AND SGN(y(n)-yc)<>SGN(y(n+1)-yc) THEN CALL Mirror
END IF
END SUB
SUB Mirror
LET i=mx*ox(n)+my*oy(n) !ox,oy: 辺に垂直で内向き 単位vector
IF 0<=i THEN EXIT SUB !後向きの交点
LET mx=mx-2*i*ox(n)
LET my=my-2*i*oy(n) !反射速度
LET bx=xc
LET by=yc
LET nb=n !反射辺 履歴
END SUB
100 LET N=100
110 LET c=0
120 FOR i=2 TO N
130 FOR k=2 TO i-1 !約数を確認する
140 IF MOD(i,k)=0 THEN GOTO 170 !ひとつでも割り切れるなら、素数でない
150 NEXT k
160 LET c=c+1 !素数
170 NEXT i
180 PRINT c !結果を表示する
190 END
SET TEXT font "Courier New Bold Italic",24
PLOT TEXT ,AT 0.3,0.2: "ABCabc"
とすると、きれいな文字が描けると思います。
通常の書体には、「標準」文字しか用意されていないため、システムでは
PLOT TEXT ,AT 0.1,0.8: "ABCabcあいう漢字" !元の書体と大きさ
DRAW PlotText("MS 明朝","",24,"ABCabcあいう漢字") WITH SHIFT(0.1,0.7)
DRAW PlotText("MS 明朝","太字",0,"ABCabcあいう漢字") WITH SHIFT(0.1,0.6)
DRAW PlotText("","斜体",0,"ABCabcあいう漢字") WITH SHIFT(0.1,0.5)
DRAW PlotText("MS 明朝","太字 斜体",24,"ABCabcあいう漢字") WITH SHIFT(0.1,0.4)
END
EXTERNAL PICTURE PlotText(f$,a$,s,s$) !原点を基準に、太字(Bold)や斜体(Italic)で文字を描く
IF f$<>"" OR s<>0 THEN SET TEXT font f$,s
IF POS(a$,"斜体")>0 THEN LET a=0.5 ELSE LET a=0
DRAW TEXT(s$) WITH SHEAR(a)
LET dx=worldx(pixelx(0)+1) !1ドットずらす
LET dy=worldy(pixely(0)+1)
IF POS(a$,"太字")>0 THEN DRAW TEXT(s$) WITH SHEAR(a)*SHIFT(dx,0)
!IF POS(a$,"太字")>0 THEN DRAW TEXT(s$) WITH SHEAR(a)*SHIFT(0,dy) !※必要に応じて
!IF POS(a$,"太字")>0 THEN DRAW TEXT(s$) WITH SHEAR(a)*SHIFT(dx,dy) !※必要に応じて
END PICTURE
EXTERNAL PICTURE TEXT(s$) !原点を基準に文字を描く
PLOT TEXT ,AT 0,0: s$
END PICTURE
!平面上のベクトル方程式とそのグラフ
OPTION ARITHMETIC COMPLEX
DEF v(a,b)=COMPLEX(a,b) !複素数の和差、実数倍の計算を対応させる
DEF fnDOT(a,b)=( a*conj(b) + conj(a)*b ) / 2 !内積 a1*b1+a2*b2
!絶対値 ベクトル |a|^2=a・a 複素数 |z|^2=z*conj(z)
SET WINDOW -8,8,-8,8 !表示領域を設定する
DRAW grid !XY座標
ASK PIXEL SIZE (-8,-8; 8,8) w,h !画像の縦横の大きさ(ドット単位)を調べる
LET cEps=0.1 !精度 ※調整が必要である
SET POINT STYLE 1 !点の形状
!例 点A(1,0)を通り、方向ベクトル(2,3)である直線の方程式を求めよ。
!参考 複素数による表現
! 点A(α=a+b*i)、d(β=c+d*i)とすると
! conj(β)*z-β*conj(z)=conj(β)*α-β*conj(α)
LET OA=v(1,0)
LET d=v(2,3)
FOR t=-3 TO 3 !t=[-∞,∞] ※範囲は調整が必要である
LET OP=OA+t*d !(x,y)=(1,0)+t*(2,3)=(1+2*t,3*t)
PLOT LINES: Re(OP),Im(OP);
NEXT t
PLOT LINES
!例 2点A(2,5)、B(-1,3)を結ぶ線分ABの方程式を求めよ。
!参考 複素数による表現
! 点A(α=a+b*i)、点B(β=c+d*i)とすると、直線ABは
! (conj(β)-conj(α))*z+(β-α)*conj(z)=conj(β)*α-β*conj(α)
LET OA=v(2,5)
LET OB=v(-1,3)
FOR t=0 TO 1 !t=[0,1]
LET OP=(1-t)*OA+t*OB !(x,y)=(1-t)*(2,5)+t*(-1,3)
PLOT LINES: Re(OP),Im(OP);
NEXT t
PLOT LINES
!例 点A(2,5)、ベクトルn=(4,3)に垂直な直線の方程式を求めよ。(内積を用いた表現)
!参考 複素数による表現
! 点A(α=a+b*i)、n(β=c+d*i)とすると
! conj(β)*z+β*conj(z)=conj(β)*α+β*conj(α)
LET a=v(2,5)
LET n=v(4,3)
FOR j=0 TO h !画面全体を走査する
LET y=worldy(j) !ドットをxy座標に変換する
FOR i=0 TO w
LET x=worldx(i)
LET p=v(x,y) !n・(p-a)=0となる点Pの軌跡
IF ABS( fnDOT(n,p-a) )<cEps THEN PLOT POINTS: x,y
NEXT i
NEXT j
!例 点C(-1,1)を中心とする半径3の円の方程式を求めよ。
!参考 複素数による表現
! 点C(α=a+b*i)とすると、|z-α|=r
LET OC=v(-1,1)
LET r=3
FOR j=0 TO h !画面全体を走査する
LET y=worldy(j) !ドットをxy座標に変換する
FOR i=0 TO w
LET x=worldx(i)
LET OP=v(x,y) !|p-c|=rとなる点Pの軌跡
IF ABS( ABS(OP-OC)-r )<cEps THEN PLOT POINTS: x,y
NEXT i
NEXT j
!例 2点A(-5,-3)、B(2,4)を直径とする円の方程式を求めよ。(内積を用いた表現)
!参考 複素数による表現
! 点A(α=a+b*i)、点B(β=c+d*i)とすると
! arg((z-α)/(z-β))=±PI/2 または |z-(α+β)/2|=|α-β|/2
LET OA=v(-5,-3)
LET OB=v(2,4)
FOR j=0 TO h !画面全体を走査する
LET y=worldy(j) !ドットをxy座標に変換する
FOR i=0 TO w
LET x=worldx(i)
LET OP=v(x,y) !PA・PB=0(円周角の定理)となる点Pの軌跡
IF ABS( fnDOT(OA-OP,OB-OP) )<cEps THEN PLOT POINTS: x,y
NEXT i
NEXT j
!例 点O(0,0)、A(2,0)、B(1,2)として、点PをOP=s*OA+t*OB、実数s,tとする。
! ��1≦s+t≦3、0≦s、0≦tの範囲を動くとき、点Pの存在範囲を図示せよ。
! ��2*s+t=1を満たすとき、点Pの存在範囲を図示せよ。
LET OA=v(2,0)
LET OB=v(1,2)
FOR s=0 TO 3 STEP 2^(-6) !s≦3 ※刻みは調整が必要である
FOR t=0 TO 3 STEP 2^(-6) !0≦sより、s+t≦3≦3+sとなる。これより、t≦3
IF 1<=s+t AND s+t<=3 THEN !��
LET OP=s*OA+t*OB
PLOT POINTS: Re(OP),Im(OP)
END IF
NEXT t
NEXT s
FOR s=-4 TO 4 STEP 2^(-6) !t=[-∞,∞] ※範囲と刻みは調整が必要である
LET t=1-2*s !2*s+t=1より
LET OP=s*OA+t*OB
PLOT POINTS: Re(OP),Im(OP) !��
NEXT s
!例 X軸上を転がる半径1の円の円周上の点Pの軌跡(サイクロイド)
LET r=1
FOR t=-3*PI TO 3*PI STEP 0.1 !※範囲と刻みは調整が必要である
LET OA=v(r*t,r) !中心A、X軸との接点Bとすると、OB=弧BPより
LET AP=v(-r*SIN(t),-r*COS(t))
LET OP=OA+AP !点Pの軌跡
PLOT LINES: Re(OP),Im(OP);
NEXT t
PLOT LINES
END
PUBLIC NUMERIC BIAS, KETA, SIGN, EPS
INPUT PROMPT "桁数=":KETA !' 2000桁まで
LET KETA = INT(KETA/4)
LET EPS = 5 !'計算誤差分(4*EPS 桁)
LET BIAS = 0 !'10000 ^ (BIAS+1) まで
LET KETA = KETA + EPS !'10000 ^ (-KETA) まで
LET SIGN = -BIAS - 1 !'多倍長数符号 A(SIGN)=1... 正 A(SIGN)=-1...負
DIM A(-BIAS-1 TO KETA)
LET X=5
!'INPUT PROMPT "LOG(X) X=":X
CALL SLOG(X,A)
CALL DISPLAY2(A)
END
EXTERNAL SUB SLOG(X,S())
DIM A(-BIAS-1 TO KETA)
FOR I=1 TO 32
IF X<=2^I THEN EXIT FOR
NEXT I
IF (2^I-X)/2^I<(X-2^(I-1))/2^(I-1) THEN
CALL SLOG2(X,S)
ELSE
CALL SLOG3(X,S)
END IF
END SUB
EXTERNAL SUB SLOG2(AX, X()) !'LOG(1-T) T=1-X/2^N (0<T<=1) → LOG((2^N-X)/2^N)
IF AX < 0 THEN
PRINT "ERROR in SLOG2"
STOP
END IF
DIM U(-BIAS - 1 TO KETA), V(-BIAS - 1 TO KETA), S(-BIAS - 1 TO KETA), N(-BIAS - 1 TO KETA)
LET NN= 1
LET U(0) = 1
LET U(SIGN) = 1
LET S(SIGN) = 1
LET F = 1
DO WHILE 2 ^ F < AX
LET F = F + 1
LOOP
LET XX = 2 ^ F - AX
LET XA = 2 ^ F
CALL LN2(N)
CALL SMUL(N,F)
IF XX=0 THEN
CALL LCOPY(X,N)
EXIT SUB
END IF
DO
CALL SMUL(U,XX)
CALL SDIV(U,XA)
CALL LCOPY(V, U)
CALL SDIV(V, NN)
CALL LADD2(S, V)
LET NN = NN+ 1
LOOP UNTIL ZERO(V)<>0
CALL LSUB (N, S, X)
END SUB
EXTERNAL SUB SLOG3(XA, X()) !'LOG((T-1)/(T+1)) T=X/2^N (1<T<=2) → LOG((X-2^N)/(X+2^N))
IF XA < 0 THEN
PRINT "ERROR in SLOG3"
STOP
END IF
DIM D(-BIAS - 1 TO KETA)
DIM M(-BIAS - 1 TO KETA), S(-BIAS - 1 TO KETA)
DO
LET K=K+1
LOOP WHILE 2 ^ (K+1) < XA
IF XA - 2 ^ (K+1) = 0 THEN
CALL LN2(X)
CALL SMUL(X,K+1)
EXIT SUB
END IF
LET N = 1
CALL LCLR (X)
LET X(0) = XA - 2^K
LET X(SIGN) = 1
CALL SDIV(X,XA+2^K)
CALL LCOPY(S, X)
DO
CALL LCOPY(M, S)
CALL SMUL(X,(XA-2^K)^2)
CALL SDIV(X,(XA+2^K)^2)
CALL LCOPY(D, X)
LET N = N + 2
CALL SDIV(D, N)
CALL LADD2(S, D)
LOOP UNTIL EQUAL(M, S)<>0
CALL SMUL(S,2)
CALL LN2(D)
CALL SMUL(D,K)
CALL LADD(D,S,X)
END SUB
EXTERNAL SUB LN2(X()) !' LOG(2) (2000桁分)
CALL LCLR (X)
LET X(SIGN)=1
FOR I = 1 TO KETA
READ IF MISSING THEN EXIT FOR:X(I)
NEXT I
DATA
6931,4718,0559,9453,0941,7232,1214,5817,6568,0755,0013,4360,2552,5412,0680,0094,9339,3621,9696,9471,5605,8633,2699,6418,6875
DATA
4200,1481,0205,7068,5733,6855,2023,5758,1305,5703,2670,7516,3507,5961,9307,2757,0828,3714,3519,0307,0386,2389,1673,4711,2335
DATA
0115,3644,9795,5239,1204,7517,2681,5749,3206,5155,5247,3413,9525,8829,5045,3007,0953,2636,6642,6541,0423,9157,8149,5204,3740
DATA
4303,8550,0801,9441,7064,1671,5186,4471,2839,9681,7178,4546,9570,2627,1631,0645,4615,0257,2074,0248,1637,7733,8963,8550,6952
DATA
6066,8341,1372,7387,3722,9289,5649,3547,0257,6265,2098,8596,9320,1965,0585,5476,4703,3067,9365,4432,5476,3274,4951,2504,0606
DATA
9438,1471,0468,9946,5062,2016,7720,4245,2452,9612,6879,4654,6193,1651,7468,1392,6725,0410,3802,5462,5965,6869,1441,9287,1608
DATA
2938,0317,2714,3677,8265,4877,5664,8508,5674,0776,4845,1464,4399,4046,1422,6031,9309,6735,4025,7444,6070,3080,9608,5047,4866
DATA
3852,3138,1816,7675,1438,6674,7664,7890,8814,3714,1985,4942,3151,9973,5488,0375,1658,6127,5352,9166,1000,7105,3558,2498,7941
DATA
4729,5092,9311,3897,1559,9820,5654,3928,7170,0072,1808,5761,0252,3688,9213,2449,7138,9320,3784,3935,3088,7748,2597,0171,5591
DATA
0708,8236,8362,7589,8425,8918,5353,0243,6342,1436,7061,1892,3678,9192,3723,1467,2321,7205,3401,6492,5687,2747,7823,4453,5347
DATA
6481,1494,1864,2386,7767,7440,6069,5626,5737,9600,8670,7625,7199,1847,3402,2651,4628,3790,4883,0620,3306,1144,6300,7371,9489
DATA
0027,4364,3965,0025,8093,6519,4430,4119,1150,6080,9487,9306,7865,1588,7090,0605,2034,6842,9736,1938,4128,9652,5565,3968,6022
DATA
1941,2292,4207,5743,2175,7489,0977,0675,2687,1158,1705,1137,0091,5894,2665,4785,9596,4890,6530,5846,0258,6683,8294,0022,8330
DATA
0538,2074,0056,7705,3046,7870,0184,1624,0441,8833,2327,9838,6349,0015,6312,1889,5606,5055,3151,2721,9939,8332,0307,5140,8426
DATA
0914,7900,1265,1682,4344,3893,5724,7278,8205,4862,7155,2741,8772,4300,2489,7945,4019,6187,2339,8086,0831,6648,1149,0930,6675
DATA
1933,9312,8904,3164,1370,6813,9777,6498,1769,7486,8903,8877,8999,1296,5036,1927,0710,8892,6410,5230,9247,8391,7373,5012,2984
DATA
2420,4995,6893,5992,2066,0220,4654,9415,1061,3918,7885,7442,4557,7510,2068,3703,0866,6194,8089,6412,1868,0779,0208,1815,8858
DATA
0001,6881,1597,3056,1866,7619,9187,3952,0076,6719,2145,9223,6720,6025,3959,5436,5416,5531,1295,1759,8994,0056,0003,6651,3567
DATA
5690,5124,5926,8257,4394,6483,1683,3262,4901,8038,2424,0824,2314,5230,6140,9638,0570,0702,5513,8770,2681,7851,6306,9025,5137
DATA
0323,4053,8021,4501,9015,3740,2950,9942,2629,9577,9647,4271,3815,7363,8017,2987,3940,7042,4217,9972,2669,6297,9939,3127,0693
DATA 5747,2404,9338,6530,8797
END SUB
!'以下、多倍長計算共通ルーチン (多倍長LOG(π)を求める、でも使用)
EXTERNAL SUB DISPLAY2(X()) !'表示
FOR K=-BIAS TO 0
IF X(K)<>0 THEN EXIT FOR
NEXT K
IF X(SIGN) = -1 THEN PRINT "- ";
IF K>=0 THEN
LET K=0
PRINT STR$(X(0));"."
ELSE
PRINT STR$(X(K));
FOR I=K+1 TO 0
LET A$=A$ & RIGHT$("000"&STR$(X(I)),4)
IF LEN(A$) = 100 THEN
PRINT A$
LET A$=""
END IF
NEXT I
IF LEN(A$) > 0 THEN
PRINT A$;"."
LET A$=""
END IF
END IF
LET S=0
FOR I=1 TO KETA-EPS
LET A$=A$ & RIGHT$("000"&STR$(X(I)),4)
IF LEN(A$) = 100 THEN
LET S=S+100
FOR J=1 TO 10
PRINT LEFT$(A$,10);" ";
IF J=5 THEN PRINT " ";
LET A$=RIGHT$(A$,LEN(A$)-10)
NEXT J
PRINT ":";S
LET A$=""
IF MOD(S,1000)=0 THEN PRINT
END IF
NEXT I
IF LEN(A$) > 0 THEN
LET S=S+LEN(A$)
LET A$=A$ & REPEAT$(" ",10)
FOR J=1 TO 9
PRINT RTRIM$(LEFT$(A$,10));" ";
IF J=5 THEN PRINT " ";
LET A$=RIGHT$(A$,LEN(A$)-10)
IF RTRIM$(A$)="" THEN EXIT FOR
NEXT J
!' PRINT ":";S
END IF
END SUB
EXTERNAL FUNCTION EQUAL(A(), B()) !'等しいかどうか
FOR I = -BIAS - 1 TO KETA-EPS
IF A(I)<>B(I) THEN
LET EQUAL=0
EXIT FUNCTION
END IF
NEXT I
LET EQUAL=-1
END FUNCTION
EXTERNAL FUNCTION ZERO(A()) !'0値かどうか
FOR I=-BIAS TO KETA-EPS
IF A(I)<>0 THEN
LET ZERO=0
EXIT FUNCTION
END IF
NEXT I
LET ZERO=-1
END FUNCTION
EXTERNAL FUNCTION GREAT(A(), B()) !'多倍長数A > 多倍長数B なら真
LET SIGNA = A(SIGN)
LET SIGNB = B(SIGN)
IF SIGNA = -1 AND SIGNB = 1 THEN
LET GREAT = 0
EXIT FUNCTION
END IF
IF SIGNA = 1 AND SIGNB = -1 THEN
LET GREAT = -1
EXIT FUNCTION
END IF
FOR I = -BIAS TO KETA
IF SIGNA = -1 AND SIGNB = -1 THEN
IF A(I) < B(I) THEN
LET GREAT = -1
EXIT FUNCTION
END IF
IF A(I) > B(I) THEN
LET GREAT = 0
EXIT FUNCTION
END IF
ELSE
IF A(I) > B(I) THEN
LET GREAT = -1
EXIT FUNCTION
END IF
IF A(I) < B(I) THEN
LET GREAT = 0
EXIT FUNCTION
END IF
END IF
NEXT I
END FUNCTION
EXTERNAL SUB LCLR(A()) !'0値セット
MAT A=ZER
LET A(SIGN) = 1
END SUB
EXTERNAL SUB LCOPY(A(), B()) !'値コピー
MAT A=B
END SUB
EXTERNAL SUB LADD(A(), B(), C()) !'多倍長同士の加算 C=A+B
LET SIGNA = A(SIGN)
LET SIGNB = B(SIGN)
IF SIGNA = 1 AND SIGNB = -1 THEN
LET B(SIGN) = 1
CALL LSUB (A, B, C)
LET B(SIGN) = -1
EXIT SUB
ELSEIF SIGNA = -1 AND SIGNB = 1 THEN
LET A(SIGN) = 1
CALL LSUB (B, A, C)
LET A(SIGN) = -1
EXIT SUB
END IF
MAT C=A+B
FOR I = KETA TO -BIAS + 1 STEP -1
IF C(I) >= 10000 THEN
LET C(I) = C(I) - 10000
LET C(I - 1) = C(I - 1) + 1
END IF
NEXT I
IF C(-BIAS) >= 10000 THEN
PRINT "OVER FLOW in LADD"
STOP
END IF
IF SIGNA = -1 AND SIGNB = -1 THEN LET C(SIGN) = -1 ELSE LET C(SIGN) = 1
END SUB
EXTERNAL SUB LADD2(A(),B()) !'多倍長同士の加算 A=A+B
DIM C(-BIAS-1 TO KETA)
CALL LADD(A,B,C)
CALL LCOPY(A,C)
END SUB
EXTERNAL SUB LSUB (A(), B(), C())!'多倍長同士の減算 C=A-B
LET SIGNA = A(SIGN)
LET SIGNB = B(SIGN)
LET A(SIGN) = 1
LET B(SIGN) = 1
IF SIGNA * SIGNB = -1 THEN
CALL LADD (A, B, C)
LET C(SIGN) = SIGNA
LET A(SIGN) = SIGNA
LET B(SIGN) = SIGNB
EXIT SUB
END IF
LET GR = GREAT(A, B)
IF SIGNA = 1 AND SIGNB = 1 THEN
IF GR<>0 THEN
MAT C=A-B
LET C(SIGN) = 1
ELSE
MAT C=B-A
LET C(SIGN) = -1
END IF
ELSE
IF GR<>0 THEN
MAT C=B-A
LET C(SIGN) = 1
ELSE
MAT C=A-B
LET C(SIGN) = -1
END IF
END IF
FOR I = KETA TO -BIAS + 1 STEP -1
IF C(I) < 0 THEN
LET C(I) = C(I) + 10000
LET C(I - 1) = C(I - 1) - 1
END IF
NEXT I
LET A(SIGN) = SIGNA
LET B(SIGN) = SIGNB
END SUB
EXTERNAL SUB LSUB2(A(),B()) !'多倍長同士の減算 A=A-B
DIM C(-BIAS-1 TO KETA)
CALL LSUB(A,B,C)
CALL LCOPY(A,C)
END SUB
EXTERNAL SUB SDIV (A(), XA) !'割り算 多倍長数A = 多倍長数A / 整数XA (1E+10程度まで)
IF XA=0 THEN
PRINT "ERROR in SDIV"
STOP
END IF
LET SIGNA = A(SIGN)
LET SG = SGN(XA)
LET XX = ABS(XA)
FOR I = -BIAS TO KETA - 1
LET R = A(I) - INT(A(I) / XX) * XX
LET A(I) = INT(A(I) / XX)
LET A(I + 1) = A(I + 1) + R * 10000
NEXT I
LET A(KETA) = INT(A(KETA) / XX)
LET A(SIGN) = SIGNA * SG
END SUB
EXTERNAL SUB SMUL (A(), XA)!'掛け算 多倍長数A = 多倍長数A * 整数XA (1E+10程度まで)
LET SIGNA = A(SIGN)
IF XA >= 0 THEN LET SG=1 ELSE LET SG=-1
LET XX = ABS(XA)
MAT A=(XX)*A
FOR I = KETA TO -BIAS + 1 STEP -1
IF A(I) >= 10000 THEN
LET R = INT(A(I) / 10000)
LET A(I) = A(I) - 10000 * R
LET A(I - 1) = A(I - 1) + R
END IF
NEXT I
IF A(-BIAS) >= 10000 THEN
PRINT "OVER FLOW in SMUL"
STOP
END IF
LET A(SIGN) = SIGNA * SG
END SUB
PUBLIC NUMERIC KETA,BIAS,EPS
INPUT PROMPT "桁数=":KETA
LET KETA=INT(KETA/4)
LET EPS=2
LET BIAS=0
LET KETA=KETA+EPS
OPTION BASE 0
DIM S(KETA),A(KETA),B(KETA),C(KETA),AA(KETA),BB(KETA),CC(KETA),M(KETA)
LET N = 1
LET A(0)=3
LET B(0)=5
LET C(0)=7
FOR I = 0 TO KETA - 1
LET R = A(I) - INT(A(I) / 161) * 161
LET A(I) = INT(A(I) / 161)
LET A(I + 1) = A(I + 1) + R * 10000
LET R = B(I) - INT(B(I) / 49) * 49
LET B(I) = INT(B(I) / 49)
LET B(I + 1) = B(I + 1) + R * 10000
LET R = C(I) - INT(C(I) / 31) * 31
LET C(I) = INT(C(I) / 31)
LET C(I + 1) = C(I + 1) + R * 10000
NEXT I
LET A(KETA) = INT(A(KETA) / 161)
LET B(KETA) = INT(B(KETA) / 49)
LET C(KETA) = INT(C(KETA) / 31)
MAT S=S+A
MAT S=S+B
MAT S=S+C
FOR I = KETA TO 0 STEP -1
IF S(I) >= 10000 THEN
LET R = INT(S(I) / 10000)
LET S(I)=S(I)-R*10000
LET S(I - 1) = S(I - 1) + R
END IF
NEXT I
DO
FOR I = 0 TO KETA - 1
LET R = A(I) - INT(A(I) / 25921) * 25921
LET A(I) = INT(A(I) / 25921)
LET A(I + 1) = A(I + 1) + R * 10000
LET R = B(I) - INT(B(I) / 2401) * 2401
LET B(I) = INT(B(I) / 2401)
LET B(I + 1) = B(I + 1) + R * 10000
LET R = C(I) - INT(C(I) / 961) * 961
LET C(I) = INT(C(I) / 961)
LET C(I + 1) = C(I + 1) + R * 10000
NEXT I
LET A(KETA) = INT(A(KETA) / 25921)
LET B(KETA) = INT(B(KETA) / 2401)
LET C(KETA) = INT(C(KETA) / 961)
MAT AA=A
MAT BB=B
MAT CC=C
LET N=N+2
FOR I = 0 TO KETA - 1
LET R = AA(I) - INT(AA(I) / N) * N
LET AA(I) = INT(AA(I) / N)
LET AA(I + 1) = AA(I + 1) + R * 10000
LET R = BB(I) - INT(BB(I) / N) * N
LET BB(I) = INT(BB(I) / N)
LET BB(I + 1) = BB(I + 1) + R * 10000
LET R = CC(I) - INT(CC(I) / N) * N
LET CC(I) = INT(CC(I) / N)
LET CC(I + 1) = CC(I + 1) + R * 10000
NEXT I
LET AA(KETA) = INT(AA(KETA) / N)
LET BB(KETA) = INT(BB(KETA) / N)
LET CC(KETA) = INT(CC(KETA) / N)
MAT S=S+AA
MAT S=S+BB
MAT S=S+CC
FOR I = KETA TO 0 STEP -1
IF S(I) >= 10000 THEN
LET R = INT(S(I) / 10000)
LET S(I)=S(I)-R*10000
LET S(I - 1) = S(I - 1) + R
END IF
NEXT I
FOR J = 0 TO KETA
IF S(J)<>M(J) THEN
MAT M = S
LET K=J
EXIT FOR
END IF
NEXT J
LOOP WHILE J<=KETA-EPS
MAT S=2*S
FOR I = KETA TO 0 STEP -1
IF S(I) >= 10000 THEN
LET S(I) = S(I) - 10000
LET S(I - 1) = S(I - 1) + 1
END IF
NEXT I
CALL WRITEDATA(S,"")
END
EXTERNAL SUB WRITEDATA(X(),Z$)
IF Z$="" THEN OPEN #1:TextWindow1 ELSE OPEN #1:NAME Z$
ERASE #1
FOR KK=-BIAS TO KETA
IF X(KK)<>0 THEN EXIT FOR
NEXT KK
PRINT #1:"SUB LN2(X())"
PRINT #1:"CALL LCLR(X)"
PRINT #1:"LET X(SIGN)=1"
PRINT #1:"FOR I=";STR$(KK);" TO KETA"
PRINT #1:"READ IF MISSING THEN EXIT FOR:X(I)"
PRINT #1:"NEXT"
PRINT #1:"DATA ";
FOR I=KK TO KETA-EPS-1
LET K=K+1
IF MOD(K,25)=0 THEN
PRINT #1:RIGHT$("000"&STR$(X(I)),4)
PRINT #1:"DATA ";
ELSE
PRINT #1:RIGHT$("000"&STR$(X(I)),4);
IF I<>0 THEN PRINT #1:",";
END IF
IF -BIAS<=0 AND I=0 THEN
PRINT #1
PRINT #1:"DATA ";
LET K=0
END IF
NEXT I
PRINT #1:RIGHT$("000"&STR$(X(KETA-EPS)),4)
PRINT #1:"END SUB"
CLOSE #1
END SUB
PUBLIC NUMERIC BIAS, KETA, SIGN, EPS
LET EPS=12
LET N=2^9-EPS
LET BIAS = 0
LET KETA =-BIAS+N+EPS
LET SIGN = -BIAS - 1
DIM X(-BIAS - 1 TO KETA)
CALL LLOGPI(X)
CALL DISPLAY2(X)
END
EXTERNAL SUB LLOGPI(X())
DIM L(-BIAS - 1 TO KETA)
DIM A(-BIAS - 1 TO KETA), B(-BIAS - 1 TO KETA)
DIM S(-BIAS - 1 TO KETA), C(-BIAS - 1 TO KETA)
CALL PI(L)
CALL SDIV(L,9*31*14699) !'1710541690073718870111737129379 で割る
CALL SDIV(L,304439)
CALL SDIV(L,49368533)
CALL SDIV2(L,27751800277)
CALL SMUL(L,101*1657) !' 544482330679994391053312457583 倍する
CALL SMUL(L,3580259)
CALL SMUL(L,5392007)
CALL SMUL2(L,168529144463)
CALL LCLR(X)
LET X(0)=1
CALL LSUB2(X, L)
CALL LCOPY(B, X)
CALL LCOPY(S, X)
LET NN = 2
DO
CALL LMUL2(B, X)
CALL LCOPY(C, B)
CALL SDIV(C, NN)
LET NN = NN + 1
CALL LADD2(S, C)
LOOP UNTIL ZERO(B)<>0
LET S(SIGN)=-1
CALL LN1710541690073718870111737129379(L)
CALL LADD2(S,L)
CALL LN544482330679994391053312457583(L)
CALL LSUB(S,L,X)
END SUB
EXTERNAL SUB SMUL2(X(),XA) !'多倍長数X = 多倍長数X * 整数XA (1E+11〜1E+14程度まで)
DIM A(-BIAS*4 TO KETA*4+3) !'(基数10000 → 基数10 に変換して計算) 精度落ち対策
LET SIGNA = X(SIGN)
IF XA >= 0 THEN LET SG=1 ELSE LET SG=-1
LET XX = ABS(XA)
FOR I=-BIAS TO KETA
LET A(I*4)=MOD(INT(X(I)/1000),10)
LET A(I*4+1)=MOD(INT(X(I)/100),10)
LET A(I*4+2)=MOD(INT(X(I)/10),10)
LET A(I*4+3)=MOD(X(I),10)
NEXT I
MAT A=(XX)*A
FOR I=KETA*4 TO -BIAS*4+1 STEP -1
IF A(I) >= 10 THEN
LET R = INT(A(I) / 10)
LET A(I) = MOD(A(I),10)
LET A(I - 1) = A(I - 1) + R
END IF
NEXT I
IF A(-BIAS*4) >= 10 THEN
PRINT "OVER FLOW in SMUL2"
STOP
END IF
FOR I=-BIAS TO KETA-1
LET X(I)=A(I*4)*1000+A(I*4+1)*100+A(I*4+2)*10+A(I*4+3)
NEXT I
LET X(SIGN)= SIGNA * SG
END SUB
EXTERNAL SUB SDIV2(X(),XA) !'多倍長数X = 多倍長数X / 整数XA (1E+11〜1E+14程度まで)
DIM A(-BIAS*4 TO KETA*4+3) !'(基数10000 → 基数10 に変換して計算) 精度落ち対策
IF XA=0 THEN
PRINT "ERROR in SDIV2"
STOP
END IF
LET SIGNA = X(SIGN)
LET SG=SGN(XA)
LET XX = ABS(XA)
FOR I=-BIAS TO KETA
LET A(I*4)=MOD(INT(X(I)/1000),10)
LET A(I*4+1)=MOD(INT(X(I)/100),10)
LET A(I*4+2)=MOD(INT(X(I)/10),10)
LET A(I*4+3)=MOD(X(I),10)
NEXT I
FOR I=-BIAS*4 TO KETA*4-1
LET R = A(I) - INT(A(I) / XX) * XX
LET A(I) = INT(A(I) / XX)
LET A(I + 1) = A(I + 1) + R * 10
NEXT I
LET A(KETA*4)=INT(A(KETA*4)/XX)
FOR I=-BIAS TO KETA-1
LET X(I)=A(I*4)*1000+A(I*4+1)*100+A(I*4+2)*10+A(I*4+3)
NEXT I
LET X(SIGN)= SIGNA * SG
END SUB
EXTERNAL SUB LMUL(A(),B(),C())!'多倍長同士の乗算 C=A*B
LET N=(KETA+BIAS)*2
IF INT(LOG2(N))<>LOG2(N) THEN
PRINT "ERROR in LMUL"
STOP
END IF
OPTION BASE 0
DIM AA(N*2),BB(N*2),CC(N*2)
FOR I=0 TO N/2-1
LET AA(2*I)=A(-BIAS+I)
LET BB(2*I)=B(-BIAS+I)
NEXT I
CALL CDFT(2*N, COS(PI/N), SIN(PI/N), AA)
CALL CDFT(2*N, COS(PI/N), SIN(PI/N), BB)
FOR I = 0 TO N-1
LET CC(2*I) = AA(2*I) * BB(2*I) - AA(2*I+1) * BB(2*I+1)
LET CC(2*I+1) = AA(2*I) * BB(2*I+1) + BB(2*I) * AA(2*I+1)
NEXT I
CALL CDFT(2*N, COS(PI/N), -SIN(PI/N), CC)
FOR I=0 TO N/2-1
IF -2*BIAS+I>=-BIAS AND -2*BIAS+I<=KETA THEN
LET C(-2*BIAS+I)=INT(CC(2*I)/N+.5)
END IF
NEXT I
FOR I=KETA TO -BIAS STEP -1
IF C(I) >=10000 THEN
LET R = INT(C(I) / 10000)
LET C(I) = C(I) - R * 10000
LET C(I - 1) = C(I - 1) + R
ELSEIF C(I)<0 THEN
LET C(I)=C(I)+10000
LET C(I-1)=C(I-1)-1
END IF
NEXT I
LET C(SIGN)=A(SIGN)*B(SIGN)
END SUB
EXTERNAL SUB LMUL2 (A(), B()) !'多倍長同士の乗算 A=A*B
DIM C(-BIAS-1 TO KETA)
CALL LMUL(A,B,C)
CALL LCOPY(A,C)
END SUB
EXTERNAL SUB CDFT(N, WR, WI, A()) !'ネット上から入手した(※原版はFORTRAN)
LET WMR = WR
LET WMI = WI
LET M = N
DO WHILE M > 4
LET L = M / 2
LET WKR = 1
LET WKI = 0
LET WDR = 1 - 2 * WMI * WMI
LET WDI = 2 * WMI * WMR
LET SS = 2 * WDI
LET WMR = WDR
LET WMI = WDI
FOR J = 0 TO N - M STEP M
LET I = J + L
LET XR = A(J) - A(I)
LET XI = A(J + 1) - A(I + 1)
LET A(J) = A(J) + A(I)
LET A(J + 1) = A(J + 1) + A(I + 1)
LET A(I) = XR
LET A(I + 1) = XI
LET XR = A(J + 2) - A(I + 2)
LET XI = A(J + 3) - A(I + 3)
LET A(J + 2) = A(J + 2) + A(I + 2)
LET A(J + 3) = A(J + 3) + A(I + 3)
LET A(I + 2) = WDR * XR - WDI * XI
LET A(I + 3) = WDR * XI + WDI * XR
NEXT J
FOR K = 4 TO L - 4 STEP 4
LET WKR = WKR - SS * WDI
LET WKI = WKI + SS * WDR
LET WDR = WDR - SS * WKI
LET WDI = WDI + SS * WKR
FOR J = K TO N - M + K STEP M
LET I = J + L
LET XR = A(J) - A(I)
LET XI = A(J + 1) - A(I + 1)
LET A(J) = A(J) + A(I)
LET A(J + 1) = A(J + 1) + A(I + 1)
LET A(I) = WKR * XR - WKI * XI
LET A(I + 1) = WKR * XI + WKI * XR
LET XR = A(J + 2) - A(I + 2)
LET XI = A(J + 3) - A(I + 3)
LET A(J + 2) = A(J + 2) + A(I + 2)
LET A(J + 3) = A(J + 3) + A(I + 3)
LET A(I + 2) = WDR * XR - WDI * XI
LET A(I + 3) = WDR * XI + WDI * XR
NEXT J
NEXT K
LET M = L
LOOP
IF M > 2 THEN
FOR J = 0 TO N - 4 STEP 4
LET XR = A(J) - A(J + 2)
LET XI = A(J + 1) - A(J + 3)
LET A(J) = A(J) + A(J + 2)
LET A(J + 1) = A(J + 1) + A(J + 3)
LET A(J + 2) = XR
LET A(J + 3) = XI
NEXT J
END IF
IF N > 4 THEN CALL BITRV2(N, A)
END SUB
EXTERNAL SUB BITRV2(N, A())
LET M = N / 4
LET M2 = 2 * M
LET N2 = N - 2
LET K = 0
FOR J = 0 TO M2 - 4 STEP 4
IF J < K THEN
LET XR = A(J)
LET XI = A(J + 1)
LET A(J) = A(K)
LET A(J + 1) = A(K + 1)
LET A(K) = XR
LET A(K + 1) = XI
ELSEIF J > K THEN
LET J1 = N2 - J
LET K1 = N2 - K
LET XR = A(J1)
LET XI = A(J1 + 1)
LET A(J1) = A(K1)
LET A(J1 + 1) = A(K1 + 1)
LET A(K1) = XR
LET A(K1 + 1) = XI
END IF
LET K1 = M2 + K
LET XR = A(J + 2)
LET XI = A(J + 3)
LET A(J + 2) = A(K1)
LET A(J + 3) = A(K1 + 1)
LET A(K1) = XR
LET A(K1 + 1) = XI
LET L = M
DO WHILE K >= L
LET K = K - L
LET L = L / 2
LOOP
LET K = K + L
NEXT J
END SUB
EXTERNAL SUB PI(X()) !'π値
CALL LCLR (X)
LET X(SIGN)=1
FOR I=0 TO KETA
READ IF MISSING THEN EXIT FOR:X(I)
NEXT I
DATA 0003
DATA
1415,9265,3589,7932,3846,2643,3832,7950,2884,1971,6939,9375,1058,2097,4944,5923,0781,6406,2862,0899,8628,0348,2534,2117,0679
DATA
8214,8086,5132,8230,6647,0938,4460,9550,5822,3172,5359,4081,2848,1117,4502,8410,2701,9385,2110,5559,6446,2294,8954,9303,8196
DATA
4428,8109,7566,5933,4461,2847,5648,2337,8678,3165,2712,0190,9145,6485,6692,3460,3486,1045,4326,6482,1339,3607,2602,4914,1273
DATA
7245,8700,6606,3155,8817,4881,5209,2096,2829,2540,9171,5364,3678,9259,0360,0113,3053,0548,8204,6652,1384,1469,5194,1511,6094
DATA
3305,7270,3657,5959,1953,0921,8611,7381,9326,1179,3105,1185,4807,4462,3799,6274,9567,3518,8575,2724,8912,2793,8183,0119,4912
DATA
9833,6733,6244,0656,6430,8602,1394,9463,9522,4737,1907,0217,9860,9437,0277,0539,2171,7629,3176,7523,8467,4818,4676,6940,5132
DATA
0005,6812,7145,2635,6082,7785,7713,4275,7789,6091,7363,7178,7214,6844,0901,2249,5343,0146,5495,8537,1050,7922,7968,9258,9235
DATA
4201,9956,1121,2902,1960,8640,3441,8159,8136,2977,4771,3099,6051,8707,2113,4999,9998,3729,7804,9951,0597,3173,2816,0963,1859
DATA
5024,4594,5534,6908,3026,4252,2308,2533,4468,5035,2619,3118,8171,0100,0313,7838,7528,8658,7533,2083,8142,0617,1776,6914,7303
DATA
5982,5349,0428,7554,6873,1159,5628,6388,2353,7875,9375,1957,7818,5778,0532,1712,2680,6613,0019,2787,6611,1959,0921,6420,1989
DATA
3809,5257,2010,6548,5863,2788,6593,6153,3818,2796,8230,3019,5203,5301,8529,6899,5773,6225,9941,3891,2497,2177,5283,4791,3151
DATA
5574,8572,4245,4150,6959,5082,9533,1168,6172,7855,8890,7509,8381,7546,3746,4939,3192,5506,0400,9277,0167,1139,0098,4882,4012
DATA
8583,6160,3563,7076,6010,4710,1819,4295,5596,1989,4676,7837,4494,4825,5379,7747,2684,7104,0475,3464,6208,0466,8425,9069,4912
DATA
9331,3677,0289,8915,2104,7521,6205,6966,0240,5803,8150,1935,1125,3382,4300,3558,7640,2474,9647,3263,9141,9927,2604,2699,2279
DATA
6782,3547,8163,6009,3417,2164,1219,9245,8631,5030,2861,8297,4555,7067,4983,8505,4945,8858,6926,9956,9092,7210,7975,0930,2955
DATA
3211,6534,4987,2027,5596,0236,4806,6549,9119,8818,3479,7753,5663,6980,7426,5425,2786,2551,8184,1757,4672,8909,7777,2793,8000
DATA
8164,7060,0161,4524,9192,1732,1721,4772,3501,4144,1973,5685,4816,1361,1573,5255,2133,4757,4184,9468,4385,2332,3907,3941,4333
DATA
4547,7624,1686,2518,9835,6948,5562,0992,1922,2184,2725,5025,4256,8876,7179,0494,6016,5346,6804,9886,2723,2791,7860,8578,4383
DATA
8279,6797,6681,4541,0095,3883,7863,6095,0680,0642,2512,5205,1173,9298,4896,0841,2848,8626,9456,0424,1965,2850,2221,0661,1863
DATA
0674,4278,6220,3919,4945,0471,2371,3786,9609,5636,4371,9172,8746,7764,6575,7396,2413,8908,6583,2645,9958,1339,0478,0275,9009
DATA 9465,7640,7895,1269,4683,9835,2595,7098,2582,2620,5224,8940
END SUB
EXTERNAL SUB LN1710541690073718870111737129379(X()) !'LOG(1710..)値
CALL LCLR(X)
LET X(SIGN)=1
FOR I=0 TO KETA
READ IF MISSING THEN EXIT FOR:X(I)
NEXT I
DATA 0069
DATA
6143,6288,7993,3268,3004,4228,2256,8485,2026,6785,3596,6394,4004,2459,4994,5470,1366,5214,8581,6415,4697,3145,7866,1523,7272
DATA
6551,2059,0127,0534,7351,7820,4920,0008,7989,9541,7800,2163,7623,0895,4887,3922,8357,3520,5004,0375,5683,9209,4332,0242,9540
DATA
1748,4435,3241,8232,0917,6048,6351,8267,6655,4103,1920,3713,6534,2808,6848,0068,3923,2800,1886,4684,2394,0286,5595,7822,8870
DATA
6824,4083,5434,5674,3002,0302,6430,7887,0940,1081,9799,5193,2835,3565,5690,4021,5682,1679,9587,2726,5741,7738,9966,8303,9374
DATA
4065,5626,7370,2317,3186,2152,1129,2984,3621,1141,6888,7106,2708,7294,1105,4881,3419,1360,3002,9792,2275,7776,7209,3100,7189
DATA
1333,2926,5906,5310,6574,2333,0024,4444,6043,7221,5935,4199,0820,3015,5200,1473,4002,4862,2284,7807,2731,8261,8953,2953,7309
DATA
4162,4615,8900,1280,1186,1445,3416,9135,4404,4277,0805,7623,1006,4866,6480,4750,1673,5797,3590,6210,4828,8466,8064,0621,5369
DATA
6822,3112,8752,9922,5756,4306,5244,5723,7782,5053,2215,5848,6850,0720,0010,0839,6060,6790,9162,7960,6519,9616,7812,3819,6481
DATA
2850,4009,5322,6067,3979,0496,8839,2466,5255,0930,4737,8771,8972,6183,6781,6485,6742,6847,7569,0628,3272,4958,9055,0595,1667
DATA
0318,1311,7655,2636,5449,8892,8994,6549,8185,5605,1410,8418,3957,3941,9585,7859,8354,6284,4894,3324,7101,4235,7355,6297,7705
DATA
6284,7948,3668,3827,3890,3916,7911,8682,2761,6156,8577,8088,8066,9387,2851,5278,4084,2809,0879,0882,6939,4694,4014,9549,7450
DATA
2911,5763,0278,3692,1766,1804,8124,9781,4074,8058,6307,1025,2785,0760,5599,0083,4081,9099,0502,6793,1794,6341,6502,0176,2868
DATA
3796,2139,9878,6835,7170,1164,2205,6497,0107,8877,3771,7488,8657,5263,9761,2416,6278,3016,1690,0953,1383,8181,7952,3541,1635
DATA
6891,5224,4409,2332,4874,2319,4524,2884,0889,5022,8222,5650,3677,3971,7593,6214,1500,2361,0686,4206,4017,9737,8034,3987,7461
DATA
5150,7437,9961,5876,6881,2221,9103,9820,1354,6600,2760,3220,1344,0667,5700,0559,0702,6840,8532,2596,9193,2134,9548,5155,8877
DATA
1115,9327,4668,8319,5471,2802,0874,9640,1131,7970,8168,2428,1598,3983,6017,5960,3281,6942,4686,9574,9764,9433,1216,4959,2387
DATA
0873,8907,8785,5093,6238,0367,4603,0384,3624,6755,5657,2459,9473,2847,7735,8517,5154,0299,6744,3440,0577,4508,6886,3276,1136
DATA
3026,8720,1951,3001,5676,9739,1394,0643,7786,6988,0521,2185,7078,9937,0618,4466,8235,0108,8657,3294,3409,0176,9410,4535,3487
DATA
5923,4566,3163,5408,2042,0034,7213,0857,1778,0402,9447,8452,8732,6232,4880,1913,2182,3249,5532,6094,1509,8743,6779,9084,9870
DATA
0148,8381,3012,8627,2066,3865,1370,4664,5664,9339,4367,0190,7057,6215,5163,9757,6009,6007,7540,5813,9957,0761,4465,5132,0577
DATA 5503,8417,6557,8706,8939,7814,1500,5247,4757,4949,9209,4162
END SUB
EXTERNAL SUB LN544482330679994391053312457583(X()) !'LOG(5444..)値
CALL LCLR(X)
LET X(SIGN)=1
FOR I=0 TO KETA
READ IF MISSING THEN EXIT FOR:X(I)
NEXT I
DATA 0068
DATA
4696,3300,2143,9266,5590,0800,8743,3179,3315,0312,4115,3479,0888,5308,1371,0786,7772,6582,8354,8087,7911,8425,1658,1624,6863
DATA
3534,2720,9432,7548,7948,6284,7447,1357,2875,4696,1898,3726,1025,5558,4562,0907,4477,6791,4979,6390,9355,8684,7181,2383,6067
DATA
5125,9038,3164,5872,4149,1463,9290,8100,8221,3858,4661,7368,8894,4392,1782,5529,1379,0706,7263,6717,7094,2864,3556,3900,7575
DATA
8220,5281,5426,2279,7293,8843,9725,1183,2375,0876,2708,1484,0473,9670,8817,3223,4819,0068,2413,2727,7063,0621,1175,4750,7107
DATA
8671,3441,3378,9146,9346,1923,8237,0526,7108,5413,6817,1946,4759,6110,2330,5046,3222,6584,6590,6347,9478,9162,1229,8258,0639
DATA
8629,0999,7506,3639,3766,9619,4748,6069,6562,5828,2302,4778,3079,2466,1935,4340,5305,9867,9470,7594,5310,3809,3799,2927,1647
DATA
2356,9062,6748,9596,1245,0147,5975,5100,6274,8333,6949,6146,2909,4481,6231,2366,8112,4857,0275,2529,1010,3037,7042,6637,0392
DATA
1670,0491,9722,4984,9411,3815,8869,2731,5703,6430,4132,8603,8424,8368,8011,9123,4089,8308,1853,8980,8362,2095,2457,1928,3638
DATA
0053,3991,4538,1624,6079,4415,8152,2109,6785,7592,9725,2195,0650,0526,5590,0422,3146,3046,8647,5876,9130,4732,3389,1245,8068
DATA
7812,3293,5439,3929,1890,9399,6703,8878,7077,5335,6941,7431,1782,2323,8457,0834,4553,9586,3123,6397,5711,0712,1356,5910,7625
DATA
2193,7131,0681,5285,6609,1095,4149,6754,7763,2836,8796,8730,4951,2823,6551,9299,6014,9348,6341,1187,0646,7366,9790,3242,0076
DATA
3159,2614,7305,1479,3803,0883,1726,8138,1385,3562,1576,6493,8245,0199,7851,4583,9672,9911,8496,3168,7333,7765,0503,4451,0920
DATA
5090,5214,6787,1314,6772,6862,3736,8572,0251,7508,8096,1615,0470,5139,3677,8073,5561,0597,8884,4253,9075,0348,7834,3251,6913
DATA
6549,9352,6478,6587,3687,6446,5803,7343,1607,6931,6148,2364,8107,6286,4138,6620,4422,4124,9848,5744,8327,3790,8854,9012,5488
DATA
6930,5446,1559,2103,7235,1105,4337,1632,8662,1702,8001,9460,1977,8871,6694,9328,1262,7307,0409,3747,7022,2234,8243,0766,1057
DATA
1794,9925,2660,2292,2678,0591,1757,8530,6030,0003,8275,0990,6180,5366,9308,0990,1612,3368,9265,3857,0729,5854,4739,4278,6728
DATA
2111,2446,8161,9364,0415,6814,3644,1779,3609,4265,9090,3322,2336,7923,4096,4595,1538,1568,3121,3374,7747,7340,2591,1985,8297
DATA
1375,4564,3882,8472,3644,4193,1371,2433,7491,7818,1991,7233,1335,2034,1296,1177,3339,7135,6549,2440,4227,1453,0204,3370,3408
DATA
9449,0546,0281,3840,9872,7548,2470,7503,6138,4063,2497,2268,8601,9381,1855,0714,6065,2571,9613,8541,6472,6325,5532,3632,6764
DATA
0684,0804,6469,2615,3651,3647,2317,6321,2200,3895,4491,6134,5365,5560,5641,2651,0168,7531,0092,4478,8313,3640,3413,7462,9541
DATA 1403,9443,4183,7689,8013,2877,3469,9226,6078,9523,0380,9531
END SUB
PUBLIC NUMERIC KETA,EPS,SIGN
INPUT PROMPT "桁数=":KETA
LET KETA=INT(KETA/4)
LET EPS=2
LET BIAS=0
LET KETA=KETA+EPS
LET SIGN=-BIAS-1
DIM A(-BIAS-1 TO KETA),S(-BIAS-1 TO KETA),T(-BIAS-1 TO KETA)
LET A(0)=1
LET S(0)=1
LET N=1
DO
MAT A=(2*N-1)*A
FOR I = 0 TO KETA - 1
LET R = A(I) - INT(A(I)/16692642/N)*(16692642*N)
LET A(I) = INT(A(I) /16692642/N)
LET A(I + 1) = A(I + 1) + R * 10000
NEXT I
LET A(KETA) = INT(A(KETA)/16692642/N)
MAT S=S+A
FOR I = KETA TO 0 STEP -1
IF S(I) >= 10000 THEN
LET R = INT(S(I) / 10000)
LET S(I) = S(I) - R * 10000
LET S(I-1) = S(I-1) + R
END IF
NEXT I
LET FL=0
FOR I=0 TO KETA
IF S(I)<>T(I) THEN
LET T(I)=S(I)
LET FL=1
LET N=N+1
EXIT FOR
END IF
NEXT I
IF FL=0 THEN EXIT DO
LOOP
MAT S=6460*S
FOR I = KETA TO 0 STEP -1
IF S(I) >= 10000 THEN
LET R = INT(S(I) / 10000)
LET S(I) = S(I) - R * 10000
LET S(I-1) = S(I-1) + R
END IF
NEXT I
FOR I = 0 TO KETA - 1
LET R = S(I) - INT(S(I)/2889)*2889
LET S(I) = INT(S(I)/2889)
LET S(I + 1) = S(I + 1) + R * 10000
NEXT I
LET S(KETA) = INT(S(KETA)/2889)
LET S(0)=S(0)+1
FOR I = 0 TO KETA - 1
LET R = S(I) - INT(S(I)/2)*2
LET S(I) = INT(S(I)/2)
LET S(I + 1) = S(I + 1) + R * 10000
NEXT I
LET S(KETA) = INT(S(KETA)/2)
CALL DISPLAY(S)
END
EXTERNAL SUB DISPLAY(X())
FOR K=-BIAS TO 0
IF X(K)<>0 THEN EXIT FOR
NEXT K
IF K > 0 THEN LET K=0
IF X(SIGN) = -1 THEN PRINT "- ";
PRINT STR$(X(K));" ";
IF K=0 THEN PRINT "."
FOR I=K+1 TO KETA-EPS
LET L=L+1
PRINT RIGHT$("000"&STR$(X(I)),4);" ";
IF I=0 THEN
PRINT "."
LET L=0
END IF
IF MOD(L,25)=0 THEN PRINT
NEXT I
PRINT
END SUB
!直列多重振り子
!参考サイト http://www.aihara.co.jp/~taiji/pendula-equations/present-node5.html
LET N=3 !振り子の数
DIM m(N) !振り子のおもりの質量
DATA 0.2, 0.3, 0.2
MAT READ m
DIM l(N) !振り子の糸の長さ
DATA 3, 3, 4
MAT READ l
DIM th(N) !振り子のy軸に対する角度
LET th(1)=2*PI/3 !初期値
LET th(2)=-PI/2
LET th(3)=PI/6
!θ[d](d=1,n)に関するラグランジュ運動方程式
! m[d,n]*l[d]^2*d/dt^2{θ[d]}
! + Σ[i=1,d-1] m[d,n]*l[d]*l[i]*d/dt^2{θ[i]}*C[d,i]
! + Σ[i=d+1,n] m[i,n]*l[d]*l[i]*d/dt^2{θ[i]}*C[d,i]
! + Σ[i=1,d-1] m[d,n]*l[d]*l[i]*(d/dt{θ[i])^2*S[d,i]
! + Σ[i=d+1,n] m[i,n]*l[d]*l[i]*(d/dt{θ[i])^2*S[d,i]
! + m[d,n]*g*l[d]*SIN(θ[d])
! = 0
LET G=9.8 !重力加速度
FUNCTION sm(k,l) !m[k,l]=Σ[j=k,l] mj
local s,j
LET s=0
FOR j=k TO l
LET s=s+m(j)
NEXT j
LET sm=s
END FUNCTION
DEF C(i,j)=COS(th(i)-th(j)) !C[i,j]=COS(θi-θj)
DEF S(i,j)=SIN(th(i)-th(j)) !S[i,j]=SIN(θi-θj)
!2階微分方程式を連立1階微分方程式にする
! ωd=d/dt{θd}とすると、R*d/dt^2{θd}=vよりd/dt{ωd}=[INV(R)*v]d
DIM R(N,N),v(N)
SUB FNC(t,x(), f()) !連立微分方程式 d/dt{Xi}=f(t,Xi)
FOR d=1 TO N !行
FOR i=1 TO N !列
IF i>d THEN !右上部分
LET R(d,i)=sm(i,N)*l(d)*l(i)*C(d,i)
ELSEIF i=d THEN !対角線
LET R(d,i)=sm(d,N)*l(d)^2
ELSE !左下部分
LET R(d,i)=sm(d,N)*l(d)*l(i)*C(d,i)
END IF
NEXT i
NEXT d
!!!MAT PRINT R;
FOR d=1 TO N !行
LET ss=0
FOR i=1 TO d-1
LET ss=ss-sm(d,N)*l(d)*l(i)*x(i)^2*S(d,i)
NEXT i
FOR i=d+1 TO N
LET ss=ss-sm(i,N)*l(d)*l(i)*x(i)^2*S(d,i)
NEXT i
LET ss=ss-sm(d,N)*G*l(d)*SIN(th(d))
LET v(d)=ss
NEXT d
!!!MAT PRINT v;
MAT R=INV(R)
MAT f=R*v
END SUB
SET WINDOW -10,10,-12,8 !描画領域
DIM w(N) !振り子のy軸に対する角速度
MAT w=ZER
LET h=0.01 !時間刻み幅 ��t
FOR t=0 TO 30 STEP h !※調整すること
SET DRAW mode hidden !ちらつき防止開始
CLEAR
DRAW PendulumN(1) !親から順に描画する
SET DRAW mode explicit !ちらつき防止終了
!WAIT DELAY 0.2 !※必要に応じて
!4次のルンゲ・クッタ法で連立微分方程式 d/dt{Xi}=f(t,Xi)を解く
DIM k1(N),k2(N),k3(N),k4(N), f(N)
DIM x(N),TT(N)
MAT x=w
CALL FNC(t,x, f)
MAT k1=h*f
MAT TT=(1/2)*k1
MAT x=w+TT
CALL FNC(t+h/2,x, f)
MAT k2=h*f
MAT TT=(1/2)*k2
MAT x=w+TT
CALL FNC(t+h/2,x, f)
MAT k3=h*f
MAT x=w+k3
CALL FNC(t+h,x, f)
MAT k4=h*f
FOR i=1 TO N
LET w(i)=w(i)+(k1(i)+2*(k2(i)+k3(i))+k4(i))/6 !x(t+h)=x(t)+(k1+2*k2+2*k3+k4)/6
NEXT i
MAT TT=h*w !ωd=d/dt{θd}より
MAT th=th+TT
!!!MAT PRINT th;
NEXT t
PICTURE PendulumN(i) !n重の振り子を描く
LET LL=l(i)
LET AA=th(i)
DRAW Pendulum(LL,m(i)) WITH ROTATE(AA) !親
IF i<N THEN DRAW PendulumN(i+1) WITH SHIFT(LL*SIN(AA),-LL*COS(AA)) !階層関係(子へ)
END PICTURE
PICTURE Pendulum(L,r) !原点を基準に振り子を描く
PLOT LINES: 0,0; 0,-L !糸
DRAW disk WITH SCALE(r)*SHIFT(0,-L) !おもり
END PICTURE
END
!図形とベクトル方程式(三角形の心)
!平面の点を「平面のベクトルとみる」と「複素数とみる」と考えられる
OPTION ARITHMETIC COMPLEX
DEF v(a,b)=COMPLEX(a,b) !複素数の和差、実数倍の計算を対応させる
DEF fnDOT(a,b)=( a*conj(b) + conj(a)*b ) / 2 !内積 a1*b1+a2*b2
!絶対値 ベクトル |a|^2=a・a 複素数 |z|^2=z*conj(z)
DEF fnNormalize(a)=a/ABS(a) !正規化
!------------------------------ ここまでがサブルーチン
SET WINDOW -8,8,-8,8 !表示領域を設定する
DRAW grid !XY座標
ASK PIXEL SIZE (-8,-8; 8,8) w,h !画像の縦横の大きさ(ドット単位)を調べる
LET cEps=0.1 !精度 ※調整が必要である
SET POINT STYLE 1 !点の形状
!例 三角形ABCの心
! C
! b /\ a
! A ── B
! c
LET OA=v(-4,-5)
LET OB=v(3,-4)
LET OC=v(4,6)
LET AB=OB-OA !辺AB
LET BC=OC-OB !辺BC
LET CA=OA-OC !辺CA
PLOT LINES: Re(OA),Im(OA); Re(OB),Im(OB) !辺ABを描く
PLOT LINES: Re(OB),Im(OB); Re(OC),Im(OC) !辺BC
PLOT LINES: Re(OC),Im(OC); Re(OA),Im(OA) !辺CA
LET a=ABS(BC) !辺BCの長さ
LET b=ABS(CA) !辺CA
LET c=ABS(AB) !辺AB
LET t=(a+b+c)/2 !ヘロンの公式より、面積S
LET S=SQR(t*(t-a)*(t-b)*(t-c))
!------------------------------
LET OI=(a*OA+b*OB+c*OC)/(a+b+c) !内心の位置ベクトル
SET AREA COLOR 4
DRAW disk WITH SCALE(0.2)*SHIFT(OI)
SET LINE COLOR 4
LET R=S/t !S=△IAB+△IBC+△ICA=1/2*c*r+1/2*a*r+1/2*b*r=r*(a+b+c)/2より
DRAW circle WITH SCALE(R)*SHIFT(OI) !内接円を描く |z-α|=r
CALL DrawLine4(OA,OB,OC)
SUB DrawLine4(OA,OB,OC) !�あ�BACを二等分する線
FOR t=0 TO 10 !t=[0,∞] ※範囲は調整が必要である
LET wAB=OB-OA
LET wAC=OC-OA
LET OP=OA+(fnNormalize(wAB)+fnNormalize(wAC))*t !ひし形AbDcの対角線AD
PLOT LINES: Re(OP),Im(OP);
NEXT t
PLOT LINES
END SUB
CALL DrawLine4(OB,OC,OA)
CALL DrawLine4(OC,OA,OB)
!------------------------------
LET OG=(OA+OB+OC)/3 !重心の位置ベクトル
SET AREA COLOR 2
DRAW disk WITH SCALE(0.2)*SHIFT(OG)
SET LINE COLOR 2
CALL DrawLine2(OA,OB,OC)
SUB DrawLine2(OA,OB,OC) !��点Aと辺BCの中点を通る線
FOR t=0 TO 10 !t=[0,∞] ※範囲は調整が必要である
LET OP=OA+(OB+OC-2*OA)*t !平行四辺形ABDCの対角線AD
PLOT LINES: Re(OP),Im(OP);
NEXT t
PLOT LINES
END SUB
CALL DrawLine2(OB,OC,OA)
CALL DrawLine2(OC,OA,OB)
!------------------------------
LET sin2A=2*S*(b^2+c^2-a^2)/(b*c)^2 !sin2A=2*cosA*sinA、余弦定理cosA=(b^2+c^2-a^2)/(2*b*c)、面積S=1/2*b*c*sinAより
LET sin2B=2*S*(c^2+a^2-b^2)/(c*a)^2
LET sin2C=2*S*(a^2+b^2-c^2)/(a*b)^2
LET OQ=(sin2A*OA+sin2B*OB+sin2C*OC)/(sin2A+sin2B+sin2C) !外心の位置ベクトル
SET AREA COLOR 3
DRAW disk WITH SCALE(0.2)*SHIFT(OQ)
SET LINE COLOR 3
LET R=a*b*c/(4*S) !正弦定理a/sinA=b/sinB=c/sinC=2*Rと面積S=1/2*b*c*sinAより
DRAW circle WITH SCALE(R)*SHIFT(OQ) !外接円を描く
!------------------------------
LET tanA=2*S/(b^2+c^2-a^2) !tanA=sinA/cosAと余弦定理cosA=(b^2+c^2-a^2)/(2*b*c)と面積S=1/2*b*c*sinAより
LET tanB=2*S/(c^2+a^2-b^2)
LET tanC=2*S/(a^2+b^2-c^2)
LET OH=(tanA*OA+tanB*OB+tanC*OC)/(tanA+tanB+tanC) !垂心の位置ベクトル
SET AREA COLOR 1
DRAW disk WITH SCALE(0.2)*SHIFT(OH)
FOR j=0 TO h !画面全体を走査する
LET y=worldy(j) !ドットをxy座標に変換する
FOR i=0 TO w
LET x=worldx(i)
LET OP=v(x,y)
SET POINT COLOR 3 !外心
IF ABS( fnDOT(OP-(OB+OC)/2,BC) )<cEps THEN PLOT POINTS: x,y !�J�BCの垂直二等分線
IF ABS( fnDOT(OP-(OC+OA)/2,CA) )<cEps THEN PLOT POINTS: x,y
IF ABS( fnDOT(OP-(OA+OB)/2,AB) )<cEps THEN PLOT POINTS: x,y
SET POINT COLOR 1 !垂心
IF ABS( fnDOT(OP-OA,BC) )<cEps THEN PLOT POINTS: x,y !�‥�Aから辺BCへの垂線 AP⊥BC
IF ABS( fnDOT(OP-OB,CA) )<cEps THEN PLOT POINTS: x,y
IF ABS( fnDOT(OP-OC,AB) )<cEps THEN PLOT POINTS: x,y
NEXT i
NEXT j
END
LET t0=TIME
PUBLIC NUMERIC N !カードの枚数
LET N=13
DIM c(N) !最初のパターン ※
DATA 1,2,3,4,5,6,7,8,9,10,11,12,13
MAT READ c
PUBLIC NUMERIC GOAL(100) !最終のパターン ※
MAT GOAL=ZER(N)
DATA -9,-8,-7,1,2,4,5,6,-3,10,11,12,13
MAT READ GOAL
PUBLIC NUMERIC LIMIT !手数の上限 ※
LET LIMIT=10
DIM A(LIMIT) !枚数
CALL backtrack(c,1,A)
PRINT "計算時間=";TIME-t0
END
EXTERNAL SUB reverse(c(),P) !先頭からP枚を裏返す
FOR i=1 TO INT(P/2) !交換
LET t=c(i)
LET c(i)=c(P-i+1)
LET c(P-i+1)=t
NEXT i
FOR i=1 TO P !反転
LET c(i)=-c(i)
NEXT i
END SUB
EXTERNAL SUB backtrack(c(),K,A()) !バックトラック法で検証する
IF K<=LIMIT THEN !手数の上限内なら
DIM x(N)
MAT x=c !save it
FOR i=1 TO N !枚数を変える
LET A(K)=i
CALL reverse(c,i) !反転
FOR j=1 TO N !最終のパターンかどうか確認する
IF c(j)<>GOAL(j) THEN EXIT FOR
NEXT j
IF j>N THEN !一致したら
LET LIMIT=K-1 !上限を狭める ※最初に見つかったもの
PRINT K;"手"
FOR j=1 TO K
PRINT A(j); !枚数
NEXT j
PRINT
!!!MAT PRINT c; !debug
ELSE
CALL backtrack(c,K+1,A) !次へ
END IF
MAT c=x !restore it
NEXT i
END IF
END SUB
LET t0=TIME
PUBLIC NUMERIC N !カードの枚数
LET N=13
DIM c(N) !最初のパターン ※
DATA 1,2,3,4,5,6,7,8,9,10,11,12,13
MAT READ c
PUBLIC NUMERIC LIMIT !手数の上限 ※
LET LIMIT=4
PUBLIC NUMERIC cMIN !最少手数
LET cMIN=LIMIT+1
DIM A(LIMIT) !枚数
CALL backtrack(c,0,A)
IF cMIN<=LIMIT THEN PRINT "最少手数=";cMIN
PRINT "計算時間=";TIME-t0
END
EXTERNAL SUB reverse(c(),P) !先頭からP枚を裏返す
FOR i=1 TO INT(P/2) !交換
LET t=c(i)
LET c(i)=c(P-i+1)
LET c(P-i+1)=t
NEXT i
FOR i=1 TO P !反転
LET c(i)=-c(i)
NEXT i
END SUB
EXTERNAL SUB backtrack(c(),K,A()) !バックトラック法で検証する
LET s=0
FOR j=1 TO N !表の枚数を確認する
IF c(j)<0 THEN LET s=s+1
NEXT j
IF s=4 THEN !一致したら
IF K<cMIN THEN LET cMIN=K !最少手数を記録する
PRINT K;"手"
FOR j=1 TO K
PRINT A(j); !枚数列
NEXT j
PRINT
MAT PRINT c; !最終のパターン
ELSE
IF K<LIMIT THEN !手数の上限内なら
DIM x(N)
MAT x=c !save it
FOR i=1 TO N !枚数を変える
IF K>=1 AND i=A(K) THEN !同じ手が続く場合は無効!
ELSE
LET A(K+1)=i
CALL reverse(c,i) !反転
CALL backtrack(c,K+1,A) !次へ
MAT c=x !restore it
END IF
NEXT i
END IF
END IF
END SUB
新掲示板開設
投稿者:白石 和夫 投稿日:2008年 7月21日(月)09時38分46秒メインの掲示板が不調のとき,こちらをご利用ください。
なお,最大500行まで書き込めることになっていますが,
実験的には251行までしか書き込めないようです。
Internet Explorerでもインデントを保持したまま表示されること,
同一人による連続書き込みに規制がかかること(スパム対策)
など,利点も多いので,将来的には本格的な移転もありえます。