一百個例題 (30 ~ 34)
Ching-Tang Tseng
Hamilton, New Zealand
31 August 2024
\ (30)實數係數一元二次方程式的根.f \ 適用於 abc657 以後版本。 \ 最新修正日期:20150220 \ (30)QuadraticEq.f \ ABC FORTH file I/O demo code \ Author : Ching-Tang Tseng, Hamilton NZ \ Date : 6 Aug 2012 \ Contact : ilikeforth@gmail.com \ Website : http://forthfortnight.blogspot.com 2 Integers I N 20 3 MATRIX coef \ BRA(i) is a primitive BASIC style Real Array in ABC FORTH : ReadCoef ( -- ) BASIC 10 run S" (30-1)QuadraticEqCoeff.f" Get-File 20 run GetOneLineData 30 let N = INT ( BRA ( 1 ) ) 40 for I = 1 to N 50 run GetOneLineData 60 let { coef ( I 1 ) = BRA ( 2 ) } 70 let { coef ( I 2 ) = BRA ( 3 ) } 80 let { coef ( I 3 ) = BRA ( 4 ) } 90 next I 100 end ; 9 Reals a b c x f(x) x1 x2 d dsq : RealRootCheck ( -- ) BASIC 10 LET { f(x) = a * x * x + b * x + c } 20 END ; 5 complexs za zb zc zx f(zx) : ComplexRootCheck ( -- ) BASIC 10 let [ za = r>zr ( a ) + r>zi ( 0 ) ] :: [ zb = r>zr ( b ) + r>zi ( 0 ) ] :: [ zc = r>zr ( c ) + r>zi ( 0 ) ] 20 let [ f(zx) = za * zx * zx + zb * zx + zc ] 30 end ; : Once ( -- ) BASIC 10 IF { a = 0 AND b = 0 } THEN 400 20 IF { a = 0 } THEN 300 30 LET { d = b * b - ( 4 * a * c ) } 40 IF { d >= 0 } THEN 100 50 GOTO 200 100 LET { dsq = SQRT ( d ) } :: { x1 = ( NEGATE b + dsq ) / ( 2 * a ) } :: { x2 = ( NEGATE b - dsq ) / ( 2 * a ) } 110 let { x = x1 } 120 run RealRootCheck 130 PRINT { " Root x1:" , x1 ; " ==> f(x1) = " , f(x) } 140 let { x = x2 } 150 run RealRootCheck 160 PRINT { " Root x2:" , x2 ; " ==> f(x2) = " , f(x) } 170 GOTO 900 200 LET { d = ABS ( ( SQRT ( ( 4 * a * c ) - b * b ) ) / ( 2 * a ) ) } 210 let { x1 = negate b / ( 2 * a ) } 220 let [ zx = r>zr ( x1 ) + r>zi ( d ) ] 230 run ComplexRootCheck 240 PRINT [ " Root x1 = " ; zx ; " ==> f(x1) = " ; f(zx) ] 245 print { " ABS(f(x1)) = " ; ZABS ( f(zx) ) } 250 let [ zx = r>zr ( x1 ) - r>zi ( d ) ] 260 run ComplexRootCheck 270 PRINT [ " Root x2 = " ; zx ; " ==> f(x2) = " ; f(zx) ] 275 print { " ABS(f(x2)) = " ; ZABS ( f(zx) ) } 280 GOTO 900 300 LET { x1 = NEGATE c / b } 310 let { f(x) = b * x1 + c } 320 PRINT { " This equation has only one root x = " ; x1 ; " ==> f(x) = " ; f(x) } 330 GOTO 900 400 PRINT " This is not an appropriate quadratic equation!" 900 RUN CR 910 END ; : test ( -- ) BASIC 10 LET { a = 8 } :: { b = -33.33 } :: { c = 9.876e2 } 20 PRINT { " Equation:( " ; a ; " )*x^2 + ( " ; b ; " )*x + ( " ; c ; " ) = 0" } 30 RUN ONCE 40 END ; : hi ( -- ) BASIC 10 PRINT " Typical real coefficient quadratic equation: ax^2 + bx + c = 0 " CR 20 PRINT " Please enter its three coefficients: a b c " CR 30 INPUTR a , b , c 40 RUN ONCE 50 END ; : main ( -- ) PAGE BASIC 10 RUN ReadCoef 20 run S" (30-2)OutputResult.f" new-file 30 run >file 40 FOR I = 1 TO N 50 LET { a = COEF ( I 1 ) } :: { b = COEF ( I 2 ) } :: { c = COEF ( I 3 ) } 60 PRINT " ( " ; I ; " )" ; { " Equation:( " ; a ; " )*x^2 + ( " ; b ; " )*x + ( " ; c ; " ) = 0" } 70 RUN Once 80 NEXT I 90 run file> 100 run S" (30-2)OutputResult.f" save-file 110 run filetype 120 END ; cr cr .( Usage: ) cr .( 1. test : for fixed data set using. ) cr .( 2. hi : for interactive input data using. ) cr .( 3. main : for file I/O data sets using. ) cr \S cr cr .( 程式用法: ) cr .( 1. test : 固定的輸入數據時使用。 ) cr .( 2. hi : 交談式輸入數據時使用。 ) cr .( 3. main : 由檔案輸入數據時使用。 ) cr
\ (31-1)FloatDot.f \ Hans Bezemer \ SFPOUT.F \ \ Simple Floating Point Output \ \ Don't attempt to output non-real numbers such as \ NANs or INFs as it will hang. \ Floating-point pictured numeric output operators : <#. ( F: r1 -- r2 ) FROUND <# ; : #. ( F: r1 -- r2 ) 10.E F/ FDUP FLOOR FSWAP FOVER F- 10.E F* FROUND F>D D>S [CHAR] 0 + HOLD ; : #S. ( F: r1 -- r2 ) BEGIN #. FDUP F0= UNTIL ; : #>. ( F: r -- ) ( c-addr u ) FDROP 0 0 #> ; : SIGN. ( flag -- ) IF [CHAR] - HOLD THEN ; [UNDEFINED] S>F [IF] : S>F ( n -- r ) S>D D>F ; [THEN] VARIABLE FDP FDP ON \ decimal point control : 10^n ( r1 n -- r2 ) 0 ?DO 10.E F* LOOP ; : #.n ( r1 n -- r2 ) 0 ?DO #. LOOP ; 1 VALUE rscale 10 VALUE rstep \ Normalize to range 1.0 <= r < STEPSIZE : fnorm ( r1 -- |r2| sign exp ) FDUP F0< 0 2>R FABS FDUP F0= 0= IF BEGIN FDUP rstep S>F F< 0= WHILE rstep S>F F/ R> rscale + >R REPEAT BEGIN FDUP 1.0E F< WHILE rstep S>F F* R> rscale - >R REPEAT THEN 2R> ; \ Convert real number r to string c-addr u in exponential \ notation with n places right of the decimal point. : f(e.) ( r n scale step -- c-addr u ) TO rstep TO rscale 0 MAX >R fnorm R> 2>R IF FNEGATE THEN 1.E R@ 10^n FSWAP FOVER F* FROUND ( make integer) FDUP FABS FROT F/ rstep S>F F< 0= IF ( overflow) rstep S>F F/ R> R> rscale + >R >R THEN <#. R> R> S>D TUCK DABS # #S 2DROP 0< IF [CHAR] - ELSE [CHAR] + THEN HOLD [CHAR] E HOLD >R FDUP F0< ( sign) R> 2>R FABS FDP @ IF ( always output decimal point ) R> #.n [CHAR] . HOLD ELSE ( conditionally output decimal point ) R@ #.n R> IF [CHAR] . HOLD THEN THEN #S. R> SIGN. #>. ; \ Convert real number r to string c-addr u in scientific \ notation with n places right of the decimal point. : f(FS.) ( r n -- c-addr u ) 1 10 f(e.) ; \ Display real number r in scientific notation right- \ justified in a field width u with n places right of \ the decimal point. : FS.R ( r n u -- ) >R f(FS.) R> OVER - SPACES TYPE ; \ Convert real number r to string c-addr u in engineering \ notation with n places right of the decimal point. : f(FE.) ( r n -- c-addr u ) 3 1000 f(e.) ; \ Display real number r in engineering notation right- \ justified in a field width u with n places right of \ the decimal point. : FE.R ( r n u -- ) >R f(FE.) R> OVER - SPACES TYPE ; \ Convert real number r to string c-addr u in fixed-point \ notation with n places right of the decimal point. : f(F.) ( F: r -- ) ( n -- c-addr u ) 0 MAX DUP >R 10^n <#. ( round) FDUP F0< ( sign) R> 2>R FABS R> #.n [CHAR] . HOLD #S. R> SIGN. #>. ; \ Display real number r in fixed-point notation right- \ justified in a field width u with n places right of \ the decimal point. : F.R ( F: r -- ) ( n u -- ) >R f(F.) R> OVER - SPACES TYPE ; \ end fvariable fpPAD 0 fpPAD 2 cells + W! 0 fpPad cell + ! 1 fpPAD ! \\\\\\\\\\\\\\\\\\\\\\\\\\\ \ (31-2)FloatDot.f CREATE FPOWERS 1E0 F, 1E1 F, 1E2 F, 1E3 F, 1E4 F, 1E5 F, 1E6 F, 1E7 F, 1E8 F, 1E9 F, 1E10 F, 1E11 F, 1E12 F, 1E13 F, 1E14 F, 1E15 F, 1E16 F, 1E17 F, 1E18 F, : f(F.) ( -- c_addr u ) ( float: r -- ) FDUP F0< FABS FDUP FLOG F>S ( minus? log10[r] ) ( float: r ) 0 MAX \ for small r, trade readability for precision <# >R PRECISION 1- R@ - ( minus? trailing ) ( R: log10[r] ) DUP 0< IF DROP \ r > 10^PRECISION R> 18 - 0 MAX DUP >R \ assuming decimal BASE, 0 ?DO 10E0 F/ LOOP F>D \ reduce range if too big for # ELSE \ ordinary numbers PRECISION FLOATS FPOWERS + F@ F* F>D \ r*10^PRECISION R> 0 ?DO # LOOP 5 0 D+ # \ round <# ROT 0 ?DO # LOOP 0 >R \ after decimal THEN [CHAR] . HOLD R> 0 ?DO [CHAR] 0 HOLD LOOP \ big num overflow #S ROT SIGN #> \ before decimal ; \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ \ (31-3)FloatDot.f \ Convert float to string 2013.10.17 BNE CREATE FPOWERS 1E0 F, 1E1 F, 1E2 F, 1E3 F, 1E4 F, 1E5 F, 1E6 F, 1E7 F, 1E8 F, 1E9 F, 1E10 F, 1E11 F, 1E12 F, 1E13 F, 1E14 F, 1E15 F, 1E16 F, 1E17 F, 1E18 F, : [PRS] FLOATS FPOWERS + F@ ; : F.RIGHT ( .right d -- d' ) 5 0 D+ # <# ROT 0 ?DO # LOOP ; : f(F.) ( -- c_addr u ) ( float: r -- ) <# FDUP F0< FABS 0 BEGIN FDUP DUP 1+ [PRS] F< 0= OVER 18 < AND WHILE 1+ REPEAT >R PRECISION 1- R@ - ( -? .right | r: log10[r]) DUP 0< IF DROP \ r >= 10^PRECISION R> 18 - 0 MAX DUP >R \ assuming decimal BASE, 0 ?DO 10E0 F/ LOOP F>D \ reduce range if too big for # ELSE PRECISION [PRS] F* F>D \ r * 10^PRECISION R> 0 ?DO # LOOP F.RIGHT 0 >R \ rounded, after decimal THEN [CHAR] . HOLD R> 0 ?DO [CHAR] 0 HOLD LOOP \ 0overflow #S ROT SIGN #> ; \ left of decimal \ Float to string with fixed number of digits after the decimal : (F.F) ( digits -- c_addr u ) ( float: r -- ) FDUP F0< SWAP FABS DUP 1+ [PRS] F* F>D <# F.RIGHT [CHAR] . HOLD #S ROT SIGN #> ;
\ (32)Zsqrt.f 5 reals a b c d |Bz| : Bzq ( f: c d -- a b ) {{ d }} f! {{ c }} f! BASIC 10 let { |Bz| = sqrt ( c * c + d * d ) } 20 let { a = sqrt ( abs ( |Bz| + c ) / 2 ) } 30 let { b = sqrt ( abs ( |Bz| - c ) / 2 ) } 40 if { d < 0 } then 60 50 goto 70 60 let { b = negate ( b ) } 70 end {{ a }} f@ {{ b }} f@ ; : test ( f: r1 r2 -- ) zdup cr cr zsqrt z. cr cr bzq fswap fs. fs. ." i " cr cr ; 20 sigdigits !
\ (33)VariablesTest.f integer i 3 variables a b c : test1 BASIC 10 let a = 1 :: b = 2 :: c = 3 20 for i = 1 to 10 30 let a = a @ + b @ + c @ 40 run cr a @ . b @ . c @ . 50 next i 60 run cr a @ . 70 end ;
\ (34)FLocal.f 8 CONSTANT /flocals : (frame) ( n -- ) FALIGN FLOATS ALLOT ; : |FRAME ( n -- ) /flocals NEGATE (frame) ; : FRAME| 0 >R BEGIN BL WORD COUNT 1 = SWAP C@ [CHAR] | = AND 0= WHILE R@ 0= IF POSTPONE FALIGN ENDIF POSTPONE F, R> 1+ >R REPEAT /flocals R> - DUP 0< ABORT" too many flocals" POSTPONE LITERAL POSTPONE (frame) ; IMMEDIATE : *h HERE 1 FLOATS - ; : *g HERE 2 FLOATS - ; : *f HERE 3 FLOATS - ; : *e HERE 4 FLOATS - ; : *d HERE 5 FLOATS - ; : *c HERE 6 FLOATS - ; : *b HERE 7 FLOATS - ; : *a HERE 8 FLOATS - ; : a *a F@ ; : b *b F@ ; : c *c F@ ; : d *d F@ ; : e *e F@ ; : f *f F@ ; : g *g F@ ; : h *h F@ ; : func1 ( F: r1 r2 -- r3 ) FRAME| b a | CR ." b = " b F. ." a = " a F. a b F+ ." a + b = " fdup F. |FRAME ; : func2 ( F: r1 -- ) FRAME| a | CR ." a = " a F. FPI 2e fln func1 CR ." a = " a F. ." result = " a F* F. |FRAME ; 12.34e func2 \s a = 12.340000 a = 0.693147 b = 3.141593 a + b = 3.834740 a = 12.340000 result = 47.320690 ok
\ (25-1)正向之位元顯示器.f \ 20140427 : 32cRuler ( -- ) CR ." =========1=========2=========3==" CR ." 12345678901234567890123456789012" CR ." ==== LSB --> MSB ===============" CR ; : 50cRuler ( -- ) CR ." =========1=========2=========3=========4=========5" CR ." 12345678901234567890123456789012345678901234567890" CR ." ========(c) 2014 Copyright, Counting Ruler========" CR ; : 64cRuler ( -- ) CR ." |========1=========2=========3=========4=========5==||======6==|" CR ." 1234567890123456789012345678901234567890123456789012345678901234" CR ." |=== LSB --> MSB ===================================||=========|" CR ; : 80cCounterRuler ( -- ) CR ." =========1=========2=========3=========4=========5=========6=========7=========8" CR ." 12345678901234567890123456789012345678901234567890123456789012345678901234567890" CR ." 09876543210987654321098765432109876543210987654321098765432109876543210987654321" CR ." 8=========7=========6=========5=========4=========3=========2=========1=========" CR ; : 32BitsDump ( un -- ) 1 32 DO 0 2 UM/MOD SWAP IF 1 0 .R ELSE 0 0 .R THEN -1 +LOOP DROP ; VARIABLE iTTT $FFFFffff iTTT ! : TEST32 ( -- ) iTTT @ CR 32BitsDump 32cRuler ; \ : unBinaryDump ( un -- ) : unBDump cr 32BitsDump 32cRuler ; \ : dBinaryDump ( ud -- ) : udBDump cr SWAP 32BitsDump 32BitsDump 64cRuler ; \ : fpBinaryDump ( f -- ) : fpBDump cr PAD F! PAD @ 32BitsDump PAD cell + @ 32BitsDump 64cRuler ; FVARIABLE fTTT 1.625E0 fTTT F! : addrBinaryDump ( addr -- ) cr DUP @ 32BitsDump CELL + @ 32BitsDump ; : TEST64 ( -- ) fTTT CR addrBinaryDump 64cRuler ; cr cr .( Usage: ) cr .( TEST32 TEST64 ) cr .( unBDump udBDump fpBDump 32BitsDump addrBinaryDump ) cr \s : 32cCounterRuler ( -- ) CR ." S=3=====|S==2=========1=========" CR ." 21098765432109876543210987654321" CR ." 01234567890123456789012345678901" CR ." S=======|S1=========2=========3=" CR ; : 64cCounterRuler ( -- ) CR ." S===6======|S=5=========4=========3=========2=========1=========" CR ." 4321098765432109876543210987654321098765432109876543210987654321" CR ." 1234567890123456789012345678901234567890123456789012345678901234" CR ." S========1=|S======2=========3=========4=========5=========6====" CR ; 1.625E3 fTTT F! ok test64 0000000000000000000000000000000000000000001001101001100100000010 =========1=========2=========3=========4=========5=========6==== 1234567890123456789012345678901234567890123456789012345678901234 LSB --> MSB =======================================S|==========S ok 1.625e3 fs. 1.62500E3 ok 1.625e3 f. 1625.00 ok binary ok 11001011001 decimal . 1625 ok \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ \ (25-2)反向之位元顯示器.f \ 20140511 1 CHARS CONSTANT /char ( -- n ) \ Length of a character : cappend ( c s -- ) \ Add c to the counted string s 1 OVER c+! COUNT 1- CHARS + C! ; : cexchange ( ca1 ca2 -- ) \ Swap characters of ca1 and ca2 2DUP 2>R C@ SWAP C@ R> C! R> C! ; : squeeze ( a1 a2 n -- a1+n a2-n ) \ Add/subtract n to/from a1/a2 TUCK - >R + R> ; : turn ( ca u -- ) \ Reverse string ca u 1- CHARS OVER + ( start-addr end-addr ) BEGIN 2DUP U< WHILE 2DUP cexchange /char squeeze REPEAT 2DROP ; : 32cRuler ( -- ) CR ." ==3=========2=========1=========" CR ." 21098765432109876543210987654321" CR ." ==== MSB <-- LSB ===============" CR ; : 50cRuler ( -- ) CR ." =========1=========2=========3=========4=========5" CR ." 12345678901234567890123456789012345678901234567890" CR ." ========(c) 2014 Copyright, Counting Ruler========" CR ; : 64cRuler ( -- ) CR ." S|==6======||=5=========4=========3=========2=========1========|" CR ." 4321098765432109876543210987654321098765432109876543210987654321" CR ." $===$===$===$===$===$===$===$===$===$= MSB <-- LSB =$===$===$===" CR ; : 96cRuler ( -- ) CR ." 8|========7====||===6=====||==5=========4=========3=========2=========1========|" CR ." 654321098765432109876543210987654321098765432109876543210987654321098765432109876543210987654321" CR ." $===$===$===$===S===$===$===$===$===$===$===$===$===$===$===$===$===$= MSB <-- LSB =$===$===$===" CR ; : 96<>Ruler ( -- ) CR ." =========1=========2=========3=========4=========5=========6=========7=========8=========9======" CR ." 123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456" CR ." 654321098765432109876543210987654321098765432109876543210987654321098765432109876543210987654321" CR ." ======9=========8=========7=========6=========5=========4=========3=========2=========1=========" CR ; CREATE BitBUF 128 allot : 32BitsDump ( un -- ) BitBUF 84 0 FILL 1 32 DO 0 2 UM/MOD SWAP IF 49 BitBUF cappend ELSE 48 BitBUF cappend THEN -1 +LOOP DROP BitBUF COUNT TURN BitBUF COUNT TYPE ; \ unBinaryDump : unBDump ( un -- ) cr 32BitsDump 32cRuler ; \ udBinaryDump : udBDump ( ud -- ) cr 32BitsDump 32BitsDump 64cRuler ; CREATE fpPAD B/FLOAT ALLOT \ fpBinaryDump : fpBDump ( f -- ) cr fpPAD F! fpPAD cell + @ 32BitsDump fpPAD @ 32BitsDump 64cRuler ; (( : fpBDump ( f -- ) cr f>r 2r> swap 32BitsDump 32BitsDump 64cRuler ; Warning(-4104): F>R is a *** deprecated *** word (see src\compat\evolve.f) : F>R R> RP@ B/FLOAT - RP! RP@ F! >R ; )) VARIABLE iTTT $FFFFffff iTTT ! : TEST32 ( -- ) iTTT @ CR 32BitsDump 32cRuler ; : addrBinaryDump ( addr -- ) cr DUP CELL + @ 32BitsDump @ 32BitsDump ; \ 以上均為:於 8 B/FLOAT 時使用 : TEST64 ( -- ) sigdigits @ 20 sigdigits ! $7fefFFFF fpPAD CELL + ! $ffffFFFF fpPad ! fpPAD CR addrBinaryDump 64cRuler cr ." Maximum positive floating point number: " fpPAD f@ fs. cr 0 fpPAD cell + ! 1 fpPAD ! fpPAD cr addrBinaryDump 64cRuler cr ." Minimum positive floating point number: " fpPAD f@ fs. cr sigdigits ! ; \ 於 10 B/FLOAT 時使用 : TEST80 ( -- ) sigdigits @ 20 sigdigits ! $7ffe fpPAD 2 CELLs + W! $ffffFFFF fpPad cell + ! $ffffFFFF fppad ! cr fpPAD 2 cells + W@ 32Bitsdump fpPad cell + @ 32bitsdump fppad @ 32bitsdump 96cRuler cr ." Maximum positive floating point number: " fpPAD f@ fs. cr 0 fpPAD 2 cells + W! 0 fpPad cell + ! 1 fpPAD ! cr fpPAD 2 cells + W@ 32Bitsdump fpPad cell + @ 32bitsdump fppad @ 32bitsdump 96cRuler cr ." Minimum positive floating point number: " fpPAD f@ fs. cr sigdigits ! ; cr cr .( Usage: ) cr .( TEST32 TEST64 TEST80) cr .( unBDump udBDump fpBDump 32BitsDump addrBinaryDump ) cr \S test64 0111111111101111111111111111111111111111111111111111111111111111 S|==6======||=5=========4=========3=========2=========1========| 4321098765432109876543210987654321098765432109876543210987654321 $===$===$===$===$===$===$===$===$===$= MSB <-- LSB =$===$===$=== Maximum positive floating point number: 1.7976931348623148800E308 0000000000000000000000000000000000000000000000000000000000000001 S|==6======||=5=========4=========3=========2=========1========| 4321098765432109876543210987654321098765432109876543210987654321 $===$===$===$===$===$===$===$===$===$= MSB <-- LSB =$===$===$=== Minimum positive floating point number: 4.9406564584124691200E-324 t41 Minnimum subnormal positive double floating point number for 8 B/FLOAT 64 bits IEEE 754 = 4.940656458412465441765687928682213723650598026143 24764425585682500675507270208751865299836361635992 379796564656 X10^ -324 與系統印出數字比較如下: 最後三位數不準,因此,18位數只有15位數準確。20140519 4.9406564584124691200E-32 test80 000000000000000001111111111111101111111111111111111111111111111111111111111111111111111111111111 8|========7====||===6=====||==5=========4=========3=========2=========1========| 654321098765432109876543210987654321098765432109876543210987654321098765432109876543210987654321 $===$===$===$===S===$===$===$===$===$===$===$===$===$===$===$===$===$= MSB <-- LSB =$===$===$=== Maximum positive floating point number: 1.1897314953572317700E4932 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 8|========7====||===6=====||==5=========4=========3=========2=========1========| 654321098765432109876543210987654321098765432109876543210987654321098765432109876543210987654321 $===$===$===$===S===$===$===$===$===$===$===$===$===$===$===$===$===$= MSB <-- LSB =$===$===$=== Minimum positive floating point number: 3.6451995318824745900E-4951 \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ \ (25-3)大型大數字顯示器.f ,可以顯示多於 256 位數的數字 \ 20140420 \ (1)起始設定最大容量為 40 cells ,最大顯示位數不會超過400位數 \ (2)起始設定值放在 TestValue \ (3)顯示前,數值經由 >XRegister 搬到 XRegister \ (4)顯示後 XRegister 的內容會被計算至 0 \ (5)被顯示的數字字串,放置在系統規劃指定的PAD1緩衝區內 \ (6)轉換出來的數字字串,顯示秩序原為顛倒,故需倒轉後才印出來 \ (7)延伸的應用為 TestValue 可以為任何數字,經 >XRegister 指令移入 XRegister \ (8)固定執行指令 UX. 顯示數字。 40 VALUE NN CREATE TestValue \ $FFFFFFFF , 0 , 0 , 0 , 0 , $ffffffff , $ffffffff , $ffffffff , $ffffffff , $ffffffff , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , $f , CREATE XRegister NN Cells allot 1 CHARS CONSTANT /char ( -- n ) \ Length of a character \ 改用cBigAppend及BigCount在PAD1區處理字串,其餘所用指令與一般大數顯示程式相同 \ : cAppend ( c s -- ) \ Add c to the counted string s \ 1 OVER c+! COUNT 1- CHARS + C! ; : cExchange ( ca1 ca2 -- ) \ Swap characters of ca1 and ca2 2DUP 2>R C@ SWAP C@ R> C! R> C! ; : squeeze ( a1 a2 n -- a1+n a2-n ) \ Add/subtract n to/from a1/a2 TUCK - >R + R> ; : turn ( ca u -- ) \ Reverse string ca u 1- CHARS OVER + ( start-addr end-addr ) BEGIN 2DUP U< WHILE 2DUP cexchange /char squeeze REPEAT 2DROP ; : X/MODS ( n -- c ) \ ( n=Divisor=base@ -- c=RemainderChar ) 0 \ n:Divisor=base@ 0:r=remainder 0 NN 1- DO \ n r XREGISTER I CELLS + @ \ n r q SWAP \ = $100000000 r UM* q M+ ( n lq hr ) rot dup >r -rot r> \ n lq hr n UM/MOD \ n r q ( ud u -- u' u" ) XREGISTER I CELLS + ! \ n r -1 +LOOP \ n r NIP \ r 9 OVER < IF 7 + THEN 48 + \ r --> c ; : ZeroCheck ( -- f ) -1 0 NN 1- DO XRegister I cells + @ 0= AND -1 +LOOP ; : (UX.) ( -- addr count ) ( addr:PAD1addr count:length ) PAD1 1024 0 FILL BEGIN BASE @ X/MODS PAD1 cBigAppend ZeroCheck UNTIL PAD1 BigCount 2DUP TURN ; : >XRegister ( addr -- ) XRegister NN cells MOVE ; : UX. ( -- ) (UX.) BigType ; : MAIN ( -- ) TestValue >XRegister CR UX. TypeCountingRuler ; cr cr .( Usage : main ) cr \s 72698566559686319077796584419189618471650841510389 :50 26657279333344476955053168367802639659104216138961 :100 38203908732692781448693729442194346215678838077397 :150 82990628789152317139462189095909821299721140924092 :200 06005527971693100647871067150635851431673698774742 :250 70692250131011998411623056863545598788156045965681 :300 70016494590478505523789394870247171196184946947116 :350 842844713173773541038882815 =========1=========2=========3=========4=========5 12345678901234567890123456789012345678901234567890 ========(c) 2014 Copyright, Counting Ruler======== ok
\ (26)數基名稱.f \ 20140501 Name of Various Number Bases \ Leo J. Scanlon, FORTH PROGRAMMING, Howard W. Sams & Co., Inc. 1982, p.157 DECIMAL \ : Binary 2 base ! ; : Ternary 3 base ! ; : Quatenary 4 base ! ; : Quinary 5 base ! ; : Senary 6 base ! ; : Septenary 7 base ! ; : Octonary 8 base ! ; \ : Octal 8 base ! ; : Novenary 9 base ! ; \ : Decimal 10 base ! ; : Undecimal 11 base ! ; : Duodecimal 12 base ! ; : Terdenary 13 base ! ; : Quaterdenary 14 base ! ; : Quindenary 15 base ! ; : Hexadecimal 16 base ! ; : Sexadecimal base ! ; : Septendecimal 17 base ! ; : Octodenary 18 base ! ; : Novemdenary 19 base ! ; : Vicenary 20 base ! ; : Duosexadecimal 32 base ! ; : Duotricinary 32 base ! ; : Sexagenary 60 base ! ;
\ (27)可令記憶體自動對準之指令.f \ 20140501 : align1 ( n -- n' ) DUP 4 MOD ?DUP IF 4 SWAP - THEN + ; \ 4 錯,還令堆疊不定 : align2 ( n -- n' ) 1- 3 OR 1+ ; \ ok : align3 ( n -- n' ) NEGATE -4 AND NEGATE ; \ ok : align4 ( c-addr -- a-addr ) 3 + -4 and ; \ ok佳 : Align5 \ addr -- addr' ; \ 0 錯 %0011 and \ clear 2 lsbs %0100 + \ next quad ; : Align6 \ addr -- addr' ; \ 0 錯 $03 + \ force to next quad unless on boundary %011 and \ clear 2 lsbs ; \ : ALIGNED+ ( a -- n) 1- 1 cells 1- tuck and - ; : aALIGNED+ ( a -- n) 1- 3 tuck and - ; : aALIGNED ( a -- a) dup aaligned+ + ; \ 對準技術問題的最佳方法就是: \ 先將現行數目加上一數,令其進入下一群數目的範圍,對 cell=4 者而言為加上 cell-1=3。 \ 然後執行一次與等於負的對準量之 AND 運算,對 cell=4 者而言為與 -4 AND。 \ 於是就能得到合理的結果,以純 Forth 的表達方式寫成的程式形如下式: : align7 ( a -- a' ) [ cell 1- ] literal + [ cell negate ] literal and ; \ ok 0 value tt : test ( n -- ) to tt cr ." test value = " tt . cr ." align1 = " tt align1 . \ XXX cr ." align2 = " tt align2 . cr ." align3 = " tt align3 . cr ." align4 = " tt align4 . cr ." align5 = " tt align5 . \ XXX cr ." align6 = " tt align6 . \ XXX cr ." align7 = " tt align7 . cr ." aligned = " tt aaligned . ; \ 當系統進入 64 位元後,勢必再有必須與 8 對準之要求,根據上述設計推導如下 : align8 ( a -- a' ) 7 + -8 and ;
\ (28)各種ROT設計範例.f \ 20140501 : ROT1 >r swap r> swap ; : ROT2 2 ROLL ; : ROT3 TUCK 2SWAP DROP ; : ROT4 over swap 2SWAP DROP ; \ NUP = over swap : ROT5 >R SWAP >R 2R> ; : ROT6 >R 2>R R> 2R> ; \ E.g., ROT using one register A: variable A : ROT7 >R >R A ! R> R> A @ ; : ROT8 A ! SWAP A @ SWAP ; \ E.g., ROT using two registers A and B: variable B : ROT9 A ! B ! >R B @ A @ R> ; 3 values t1 t2 t3 1 to t1 2 to t2 3 to t3 : .3t . . . ; : @3t t3 t2 t1 ; : pre cr @3t .3t @3t ; : aft ." ==> " .3t ; : main ( -- ) pre rot1 aft cr @3t .3t @3t rot2 ." ==> " .3t cr @3t .3t @3t rot3 ." ==> " .3t cr @3t .3t @3t rot4 ." ==> " .3t cr @3t .3t @3t rot5 ." ==> " .3t cr @3t .3t @3t rot6 ." ==> " .3t cr @3t .3t @3t rot7 ." ==> " .3t cr @3t .3t @3t rot8 ." ==> " .3t cr @3t .3t @3t rot1 ." ==> " .3t ;
\ (29)標準之多項式計算程式 2012-09-20 \ Polynomial equation \ P(N)=A(0)+A(1)*X^1+A(2)*X^2+......+A(N)*X^N 3 INTEGERS I N N-1 2 REALS X P 10 ARRAY A : SETUP-POLYNOMIAL-COEFFICIENTS BASIC 10 REM (1)The degree of polynomial is N. 20 LET N = 4 30 REM (2)Set all coefficients in A(N) to be 0. N=0,1,2...n 40 FOR I = 0 TO N 50 LET { A ( I ) = 0 } 60 NEXT I 70 REM (3)Put all coefficients into A(N). 80 LET { A ( 0 ) = -5 } :: { A ( 1 ) = 2 } :: { A ( 2 ) = -1 } :: { A ( 3 ) = 2 } :: { A ( 4 ) = 3 } 90 END ; : EVALUATING-POLYNOMIAL BASIC 10 REM 20 REM Typical program 30 REM 40 LET { P = A ( N ) } 50 FOR I = 0 TO N - 1 60 LET N-1 = N - I - 1 70 LET { P = P * X + A ( N-1 ) } 80 NEXT I 90 END ; : POOREVAL ( x -- p ) {{ X }} F! {{ P = 3 * X ^ 4 + 2 * X ^ 3 - X ^ 2 + 2 * X - 5 }} P ; : SOSOEVAL ( x -- p ) {[ X }} F! {{ P = 3 * X * X * X * X + 2 * X * X * X - X * X + 2 * X - 5 }} P ; : GOODEVAL ( x -- p ) {{ X }} F! SETUP-POLYNOMIAL-COEFFICIENTS EVALUATING-POLYNOMIAL P ; : main1 sigdigits @ >r 18 sigdigits ! cr cr ." POOREVAL P(pi)^4 = " fpi pooreval pooreval pooreval pooreval fs. cr cr ." SOSOEVAL P(pi)^4 = " fpi sosoeval sosoeval sosoeval sosoeval fs. cr cr ." GOODEVAL P(pi)^4 = " fpi goodeval goodeval goodeval goodeval fs. cr cr r> sigdigits ! ; main1 \ 多項式係數指標以反向表示時的計算程式 \ F(X)=A(0)*X^N+A(1)*X^(N-1)+........+A(N-1)*X^1+A(N) \ 自動控制教科書中所使用的實際範例 \ Test for F(X)=X^4+15*X^3+270*X^2+1600*X+2000 : INIT1 BASIC 10 LET N = 4 20 LET { A ( 0 ) = 1 } 30 LET { A ( 1 ) = 15 } 40 LET { A ( 2 ) = 270 } 50 LET { A ( 3 ) = 1600 } 60 LET { A ( 4 ) = 2000 } 70 END ; COMPLEX F(X) COMPLEX (X) REAL ABSF(X) 10 [ARRAY] ZA \ 將實數係數陣列轉換成複數係數陣列 3 INTEGERS II JJ NN \ 指標有不得再重覆使用於上列中者之困擾 : ZINIT BASIC 10 LET NN = N \ 方次與實數係數在算完之後均未變 20 FOR JJ = 0 TO NN \ 指標有不得再重覆使用於上列中者之困擾 30 LET [ ZA ( JJ ) = R>ZR ( A ( JJ ) ) ] 40 NEXT JJ 50 END ; : FUNCTION(X) BASIC 10 RUN ZINIT 20 LET [ (X) = ( -3.5 - 2.4 i ) ] 30 LET [ F(X) = ZA ( 0 ) ] 40 FOR II = 1 TO NN \ 指標有不得再重覆使用於上列中者之困擾 50 LET [ F(X) = F(X) * (X) + ZA ( II ) ] 60 NEXT II 70 LET { ABSF(X) = ZABS ( F(X) ) } 80 END ; \ 印出結果 : MAIN2 BASIC 10 FOR I = 1 TO N 20 RUN FUNCTION(X) 30 PRINT " F(X( " ; I ; " )) = " ; [ F(X) ] 40 PRINT " ABS(F(X( " ; I ; " )))=" ; { ABSF(X) } 50 PRINT " " 60 NEXT I 70 END ; MAIN2 \S POOREVAL P(pi)^4 = 3.20575403126800320E172 SOSOEVAL P(pi)^4 = 3.20575403126795584E172 GOODEVAL P(pi)^4 = 3.20575403126795584E172 F(X( 1 )) = 1225.31950000 - 1260.67200000 i ABS(F(X( 1 )))= 1758.03918291 F(X( 2 )) = 1225.31950000 - 1260.67200000 i ABS(F(X( 2 )))= 1758.03918291 F(X( 3 )) = 1225.31950000 - 1260.67200000 i ABS(F(X( 3 )))= 1758.03918291 F(X( 4 )) = 1225.31950000 - 1260.67200000 i ABS(F(X( 4 )))= 1758.03918291 ok
\ Recursive in BASIC \ 能執行自用副程式之BASIC性能展示 \ 注意!這只是一個在BASIC環境中強行使用recurse的示範程式。 \ 有效計算範圍只在12以下有效,13以上都是錯的。 2 integers u u! : (u!) ( -- ) BASIC 10 if u = 1 then 50 \ 結束叫用自己時,所需要的終止條件 20 let u! = u! * u 30 let u = u - 1 40 run recurse \ 以上為叫用自己時,每次都必須執行的內容 50 end ; : BFact ( u -- u! ) [[ u ]] ! BASIC 10 let u! = 1 20 if u = 0 then 40 \ 以上為不能在每次叫用自己時都執行的內容 30 run (u!) 40 end u! ; : Ffact ( u -- u! ) DUP 0= if DROP 1 else DUP 1- recurse * then ; \s \ ********************************************************** \ 原 hanoi 程式將左邊(left)的疊片搬到中間(middle),BASIC則改為left搬到right \ 程式的特色在展示局部變數與叫用自用副程式的功能均可在BASIC式程式中使用 CREATE peg1 ." left " CREATE peg2 ." right " \ peg2換成right CREATE peg3 ." middle " \ peg3換成middle : .string ( addr -- ) COUNT TYPE ; : (hanoi) ( n peg1 peg2 peg3 -- ) LOCALS| vvia tto ffrom n | \ 局部變數 BASIC 10 if n = 1 then 30 \ 結束叫用自用副程式的條件在此 20 goto 50 30 run cr ." Move disk from " ffrom .string ." to " tto .string 40 goto 100 50 run n 1- ffrom vvia tto recurse \ 可以多次使用叫用自用副程式 => 1 ffrom tto vvia recurse => n 1- vvia tto ffrom recurse 100 end ; : hanoi ( n -- ) peg1 peg2 peg3 (hanoi) ; (( \ 原始參考程式 CREATE peg1 ," left " CREATE peg2 ," middle " CREATE peg3 ," right " : .string ( addr -- ) COUNT TYPE ; : MOVE-DISK ( n peg1 peg2 peg3 -- ) LOCALS| vvia tto ffrom n | n 1 = IF CR ." Move disk from " ffrom .string ." to " tto .string ELSE n 1- ffrom vvia tto RECURSE 1 ffrom tto vvia RECURSE n 1- vvia tto ffrom RECURSE THEN ; : test ( n -- ) peg1 peg2 peg3 MOVE-DISK ; )) \ ********************************************************* 2 integers i0 i9 : (ex) ( -- ) BASIC 10 if i0 > i9 then 100 \ 結束recurse的條件 20 let i0 = i0 + 5 30 run i0 . 40 run recurse \ 以上為recurse的部份 100 let i0 = 0 \ 歸零才可以供下一次繼續使用 110 end ; : ex ( n -- ) [[ i9 ]] ! \ 不可以recurse的部份 BASIC 10 run (ex) 20 end ; cr cr .( Usage: ) cr .( u Bfact u. ) cr .( u Ffact u. ) cr .( n hanoi ) cr .( n ex ) cr \ .( n peg1 peg2 peg3 MOVE-DISK ) cr
\ (22)Asmdiv.f \ 20140313 code asm/MOD ( n1 n2 -- r q ) mov ecx, edx pop eax cdq idiv ebx push edx mov ebx, eax mov edx, ecx next c; \ : asmMOD ( n1 n2 -- r ) asm/MOD DROP ; \ : asm/ ( n1 n2 -- q ) asm/MOD NIP ; code asm/ ( n1 n2 -- q ) mov ecx, edx \ save UP pop eax \ 被除數 cdq idiv ebx \ 除數 mov ebx, eax \ 商 mov edx, ecx \ restore UP next c; \S Win32Forth原系統中的除法指令( / ),執行結果與數學計算之基本規則不符。 例如:執行 -15 4 / . 時會得到不合理的 -4,合理結果應該是 -3。 大部份Forth系統及C語言系統,均輸出-3而非-4,因此,必須重新設計/及/MOD。 臨時以高階定義方式完成之/指令,變通性設計如下: : / ( n1 n2 -- q ) >r s>d r> sm/rem nip ; 參考VFX Forth系統及Win32Forth系統自身內的SM/REM內容便可以仿照設計,資料如下: in VFX forth see / code / ( n1 n2 -- n3 ) mov eax, [ebp] cdq idiv ebx mov ebx, eax lea ebp, [ebp+04] next, 其中: CDQ 指令為有號數除法專用指令,執行時會將EAX暫存器的最高位元值填滿整個EDX EAX ==> EDX:EAX IDIV 來源運算元 指令用於有號數除法運算。上例為 IDIV EBX。 EBX放的是除數,被除數則放在EDX:EAX。 執行後,商放在EAX,餘數放在EDX。 in Win32Forth SEE SM/REM SM/REM IS CODE ( $401C28 8BCA ) mov ecx, edx ( $401C2A 5A ) pop edx ( $401C2B 58 ) pop eax ( $401C2C F7FB ) idiv ebx ( $401C2E 52 ) push edx ( $401C2F 8BD8 ) mov ebx, eax ( $401C31 8BD1 ) mov edx, ecx 測試結果: -15 -4 asm/ . 3 ok -15 4 asm/ . -3 ok 15 4 asm/ . 3 ok 15 -4 asm/ . -3 ok
\ (23)CubicEquation.f \ Cube roots of a real coefficients cubic equation: a0x^3+a1x^2+a2x+a3=0 \ Author: Ching-Tang Tseng \ Date: 20140321 (( \ 以下列簡易設計之導得函數fcbrt直接計算,會得到極大的誤差。 \ 實測驗證後更可凸顯出正確設計fcbrt函數的重要性。 \ 自20140430起,fcbrt已建進V654以後的版本,函數名稱固定為CBRT。 : fcbrt ( F: N -- N^1/3) fabs 1e 3e f/ f** ; : fcbrt ( F: N -- N^1/3) fdup f0= if fdrop 0e0 exit then FDUP F0< FABS ( F: -- |N|) ( -- f) FDUP FSQRT ( F: -- N x0 ) BEGIN FOVER FOVER FTUCK FDUP F* F/ FSWAP F2* F+ 3E0 F/ FTUCK F- FOVER F/ FABS 1.0E-8 F< UNTIL FTUCK FDUP F* F/ FSWAP F2* F+ 3E0 F/ IF FNEGATE THEN ; ' fcbrt RDEF cbrt )) \ Cubic Equation: a0x^3 + a1x^2 + a2x + a3 = 0 \ 1.三實根 1, -3, 5 \ 2.三重實根 3 \ 3.一實根,共軛複數根 11 reals a0 a1 a2 a3 q r s t R1 Zr Zi : GetCoefficients basic \ 10 let { a0 = 1 } :: { a1 = -3 / a0 } :: { a2 = -13 / a0 } :: { a3 = 15 / a0 } \ 10 let { a0 = 1 } :: { a1 = -9 / a0 } :: { a2 = 27 / a0 } :: { a3 = -27 / a0 } 10 let { a0 = 1 } :: { a1 = 20 / a0 } :: { a2 = 600 / a0 } :: { a3 = 1200 / a0 } 20 end ; 2 reals x f(x) : CheckRealRoot basic 10 let { f(x) = a0 * x * x * x + a1 * x * x + a2 * x + a3 } 20 end ; 7 complexs z za1 za2 za3 f(z) f(z1) f(z2) : CheckComplexRoot basic 10 let [ za1 = r>zr ( a1 ) ] :: [ za2 = r>zr ( a2 ) ] :: [ za3 = r>zr ( a3 ) ] 20 let [ f(z) = z * z * z + za1 * z * z + za2 * z + za3 ] 30 end ; : CheckConjugateComplexRoots basic 10 let [ z = r>zr ( Zr ) + r>zi ( Zi ) ] 20 run CheckComplexRoot 30 let [ f(z1) = f(z) ] 40 let [ z = r>zr ( Zr ) - r>zi ( Zi ) ] 50 run CheckComplexRoot 60 let [ f(z2) = f(z) ] 70 end ; : Compute basic 10 let { q = ( 3 * a2 - a1 * a1 ) / 9 } :: { r = ( 9 * a1 * a2 - 27 * a3 - 2 * a1 * a1 * a1 ) / 54 } :: { s = cbrt ( r + sqrt ( abs ( q * q * q + r * r ) ) ) } :: { t = cbrt ( r - sqrt ( abs ( q * q * q + r * r ) ) ) } :: { R1 = s + t - a1 / 3 } :: { Zr = negate ( ( s + t ) / 2 + a1 / 3 ) } :: { Zi = abs ( ( sqrt ( 3 ) / 2 ) * ( s - t ) ) } 20 end ; 4 reals dlt dlt1 dlt2 sigma \ Discriminatory analysis \ delta > 0 one real root, two conjugate complex roots 一實根,二共軛複數根 \ delta = or < 0 three real toots 三個實根 : delta basic 10 let { dlt1 = ( ( a1 * a1 * a1 ) / ( 27 * a0 * a0 * a0 ) ) + ( a3 / ( 2 * a0 ) ) - ( a1 * a2 ) / ( 6 * a0 * a0 ) } :: { dlt2 = ( a2 / ( 3 * a0 ) ) - ( a1 * a1 ) / ( 9 * a0 * a0 ) } :: { dlt = ( dlt1 * dlt1 ) + ( dlt2 * dlt2 * dlt2 ) } 20 print { " delta = " ; dlt } 30 end ; : delta>0 basic 10 run cr 20 print " delta > 0 means there are one real root and two conjugate complex roots." 30 run cr 40 let { x = R1 } 50 print { " Root x1 = " ; x } 60 run CheckRealRoot 70 print { " f( x1 ) = " ; f(x) } 80 run cr 90 print { " Root x2 = " ; Zr ; " + " ; Zi ; " i" } 100 run CheckConjugateComplexRoots 110 print [ " f( x2 ) = " ; f(z1) ] 115 print { " ABS(f(x2)) = " ; ZABS ( f(z1) ) } 120 run cr 130 print { " Root x3 = " ; Zr ; " - " ; Zi ; " i" } 140 print [ " f( x3 ) = " ; f(z2) ] 145 print { " ABS(f(x3)) = " ; ZABS ( f(z2) ) } 150 run cr 160 end ; : delta=<0 basic 10 run cr 20 print { " delta = or < 0 means there are three real roots. " } 30 run cr 40 print { " Root x1 = " ; R1 } 50 print { " f( x1 ) = " ; f(x) } 60 run cr 70 let { x = Zr + Zi } 80 print { " Root x2 = " ; x } 90 run CheckRealRoot 100 print { " f( x2 ) = " ; f(x) } 110 run cr 120 let { x = Zr - Zi } 130 print { " Root x3 = " ; x } 140 run CheckRealRoot 150 print { " f( x3 ) = " ; f(x) } 160 run cr 170 end ; : CubeRoots basic 10 run cr 20 run Delta 30 run Compute 40 if { dlt > 0 } then 70 50 run delta=<0 60 goto 80 70 run delta>0 80 end ; : test basic 10 run GetCoefficients 20 print " Typic cubic equation is: a0x^3 + a1x^2 + a2x + a3 = 0" 30 print { " a0 = " ; a0 ; " a1 = " ; a1 ; " a2 = " ; a2 ; " a3 = " ; a3 } 40 run CubeRoots 50 end ; : hi basic 10 print " Typical cubic equation is: a0x^3 + a1x^2 + a2x + a3 = 0 " 20 print " Please enter 4 coefficients a0 a1 a2 a3 " 30 inputr a0 , a1 , a2 , a3 40 let { a0 = a0 / a0 } :: { a1 = a1 / a0 } :: { a2 = a2 / a0 } :: { a3 = a3 / a0 } 50 run CubeRoots 60 end ; 2 integers i n 20 4 matrix Coef : ReadCoef basic 10 run S" (23-1)CubicEqCoef.f" Get-File 20 run GetOneLineData 30 let n = INT ( BRA ( 1 ) ) 40 for i = 1 to n 50 run GetOneLineData 60 let { coef ( i 1 ) = BRA ( 2 ) } 70 let { coef ( i 2 ) = BRA ( 3 ) } 80 let { coef ( i 3 ) = BRA ( 4 ) } 90 let { coef ( i 4 ) = BRA ( 5 ) } 90 next i 100 end ; : main basic 10 run ReadCoef 20 run cr 30 for i = 1 to n 40 print " Typic cubic equation is: a0x^3 + a1x^2 + a2x + a3 = 0" 50 print " For given data set( " ; i ; " )" 60 let { a0 = Coef ( i 1 ) } :: { a1 = Coef ( i 2 ) } :: { a2 = Coef ( i 3 ) } :: { a3 = Coef ( i 4 ) } 70 print { " a0 = " ; a0 ; " a1 = " ; a1 ; " a2 = " ; a2 } 80 print { " a3 = " ; a3 } 90 let { a0 = a0 / a0 } :: { a1 = a1 / a0 } :: { a2 = a2 / a0 } :: { a3 = a3 / a0 } 100 run CubeRoots 110 print " ====================================================================" 120 next i 130 end ; cr cr .( 程式用法: ) cr .( 1. test : 固定的輸入數據時使用。 ) cr .( 2. hi : 交談式輸入數據時使用。 ) cr .( 3. main : 由檔案輸入數據時使用。 ) cr \S for 8 B/FLOAT ABC V654 system 18 sigdigits ! main Fileid is: 1080 96 Bytes are read into the Fadr RAM buffer! Typic cubic equation is: a0x^3 + a1x^2 + a2x + a3 = 0 For given data set( 1 ) a0 = 2.00000000000000000 a1 = 0.00000000000000000E0 a2 = 1.00000000000000000 a3 = 4.00000000000000000 delta = 4.03703703703703744 delta > 0 means there are one real root and two conjugate complex roots. Root x1 = -1.37879670012954912 f( x1 ) = 1.15463194561016272E-14 Root x2 = .689398350064774528 + 1.55750128578313152 i f( x2 ) = -5.32907051820075136E-15 - 1.26565424807267840E-14 i Root x3 = .689398350064774528 - 1.55750128578313152 i f( x3 ) = -4.44089209850062656E-15 + 1.28785870856518160E-14 i ==================================================================== Typic cubic equation is: a0x^3 + a1x^2 + a2x + a3 = 0 For given data set( 2 ) a0 = 1.00000000000000000 a1 = 9.00000000000000000 a2 = 5.00000000000000000 a3 = 1.00000000000000000 delta = 5.62962962962967616 delta > 0 means there are one real root and two conjugate complex roots. Root x1 = -8.42030108523868416 f( x1 ) = -2.13162820728030048E-14 Root x2 = -.289849457380658 + .186407861904320 i f( x2 ) = -1.33226762955018784E-15 + 2.22044604925031328E-16 i Root x3 = -.289849457380658 - .186407861904320 i f( x3 ) = -1.55431223447521920E-15 - 1.11022302462515664E-16 i ==================================================================== Typic cubic equation is: a0x^3 + a1x^2 + a2x + a3 = 0 For given data set( 3 ) a0 = 1.00000000000000000 a1 = 2.00000000000000000 a2 = 3.00000000000000000 a3 = 4.00000000000000000 delta = 1.85185185185185152 delta > 0 means there are one real root and two conjugate complex roots. Root x1 = -1.65062919143938784 f( x1 ) = 1.77635683940025056E-15 Root x2 = -.174685404280306 + 1.54686888723139616 i f( x2 ) = 1.33226762955018784E-15 + 0.00000000000000000E0 i Root x3 = -.174685404280306 - 1.54686888723139616 i f( x3 ) = 2.22044604925031328E-15 + 0.00000000000000000E0 i ==================================================================== Typic cubic equation is: a0x^3 + a1x^2 + a2x + a3 = 0 For given data set( 4 ) a0 = 1.00000000000000000 a1 = -3.00000000000000000 a2 = -13.0000000000000000 a3 = 15.0000000000000000 delta = -151.703703703703680 delta = or < 0 means there are three real roots. Root x1 = 1.00000000000000000 f( x1 ) = 1.77635683940025056E-15 Root x2 = 5.00000000000000000 f( x2 ) = 0.00000000000000000E0 Root x3 = -2.99999999999999936 f( x3 ) = 1.42108547152020032E-14 ==================================================================== Typic cubic equation is: a0x^3 + a1x^2 + a2x + a3 = 0 For given data set( 5 ) a0 = 1.00000000000000000 a1 = -9.00000000000000000 a2 = 27.0000000000000000 a3 = -27.0000000000000000 delta = 0.00000000000000000E0 delta = or < 0 means there are three real roots. Root x1 = 3.00000000000000000 f( x1 ) = 1.42108547152020032E-14 Root x2 = 3.00000000000000000 f( x2 ) = 0.00000000000000000E0 Root x3 = 3.00000000000000000 f( x3 ) = 0.00000000000000000E0 ==================================================================== Typic cubic equation is: a0x^3 + a1x^2 + a2x + a3 = 0 For given data set( 6 ) a0 = 1.00000000000000000 a1 = 20.0000000000000000 a2 = 600.000000000000000 a3 = 1200.00000000000000 delta = 4982222.22222222208 delta > 0 means there are one real root and two conjugate complex roots. Root x1 = -2.13581907909972992 f( x1 ) = -1.36424205265939232E-12 Root x2 = -8.93209046045013504 + 21.9559354517858656 i f( x2 ) = -2.72848410531878464E-12 + 1.81898940354585632E-12 i Root x3 = -8.93209046045013504 - 21.9559354517858656 i f( x3 ) = -1.81898940354585632E-12 - 1.81898940354585632E-12 i ==================================================================== Typic cubic equation is: a0x^3 + a1x^2 + a2x + a3 = 0 For given data set( 7 ) a0 = 1.00000000000000000 a1 = -5.00000000000000000 a2 = 8.00000000000000000 a3 = -4.00000000000000000 delta = 1.04083408558608432E-17 delta > 0 means there are one real root and two conjugate complex roots. Root x1 = 1.00000000000000000 f( x1 ) = 0.00000000000000000E0 Root x2 = 2.00000000000000000 + 0.00000000000000000E0 i f( x2 ) = 0.00000000000000000E0 + 0.00000000000000000E0 i Root x3 = 2.00000000000000000 - 0.00000000000000000E0 i f( x3 ) = 0.00000000000000000E0 + 0.00000000000000000E0 i ==================================================================== ok (23-1)CubicEqCoef.f 的內容: 7 1 2 0 1 4 2 1 9 5 1 3 1 2 3 4 4 1 -3 -13 15 5 1 -9 27 -27 6 1 20 600 1200 7 1 -5 8 -4
\ (24)整數之cbrt.f \ A' = ( ( n / A * A ) + 2 * A ) / 3 \ A' = ( ( n / A * A ) + A ) / 2 0 value Turnning 0 value Result : cbrtf1 ( n1 -- n2 ) 0 to Turnning 0 to Result 1 \ n1 A begin >r dup r@ r@ * / r@ + 2/ \ n1 A' rs: A r> 2dup >= if 1 +to Turnning to Result else drop then \ n1 A' Turnning 19 > \ at least 5 times for condition = in 32 bits system until 2drop Result ; (( : fcbrt1 ( f: |x| -- |x|^[1/3] ) fln 3e0 f/ fexp ; : cbrtf1 s>f fcbrt1 f>s ; )) : F**2 FDUP F* ; 3 S>D D>F FCONSTANT F=3 : X' ( F: N x -- x') FTUCK F**2 F/ FSWAP F2* F+ F=3 F/ ; \ The magic number 1E-8 needs no change, even when extended (80-bit) precision \ is needed. : CONVERGED? ( F: x' x x' --) ( -- f) F- FOVER F/ FABS 1.0E-8 F< ; : FCBRT2 ( F: N -- N^1/3) FDUP F0< FABS ( F: -- |N|) ( -- f) FDUP FSQRT ( F: -- N x0 ) BEGIN FOVER FOVER X' FTUCK CONVERGED? UNTIL X' IF FNEGATE THEN ; : cbrtf2 s>f fcbrt2 f>s ; 0 value cnt : test 0 to cnt \ 2147483647 2140000000 9000000 8000000 do \ cr i . i cbrtf1 i cbrtf2 <> if 1 +to cnt cr ." i = " i . ." , cbrtf1= " i cbrtf1 dup . ." , i^3 = " dup dup * * . ." , cbrtf2= " i cbrtf2 dup . ." , i^3 = " dup dup * * . then loop cr cnt . ." errors!" cr ." finished!" ; \s \ 以此牛頓法開平方程式為根據: A' = ( n / A + A ) / 2 : sqrt9 ( square -- root ) DUP 1 < IF DROP 0 EXIT THEN dup \ 起始猜測A為n begin 2dup / over + 2/ \ 計算(N/A+A)/2 >r dup r@ > \ A>(N/A+A)/2 ? while drop r> \ A>(N/A+A)/2時,則A換成(N/A+A)/2。 repeat nip r> drop \ 當A<=(N/A+A)/2時,A即為所求。 ; \ 開發出下列牛頓法開立方程式: A' = ( ( n / A * A ) + A ) / 2 : cbrt ( n1 -- n2 ) DUP 1 < \ These two lines guard against a negative input. IF DROP 0 EXIT THEN 1 \ n --- un, for n>0 only. 19 0 DO \ 64 位元的系統須為至少36,32位元的系統19便可。 >r dup r@ r@ * \ n n A*A / r> + 2/ \ n (n/(A*A)+A)/2, 注意!A若為0,n/A會不能執行。 LOOP \ n A' DUP DUP DUP * * \ n A' A'^3 >R SWAP R> U< \ A' f check IF ABS 1- THEN \ aquare root, correct it, if needed. ;
\ Example 11. Random numbers VARIABLE RND ( seed ) HERE RND ! ( initialize seed ) : RANDOM ( -- n, a random number within 0 to 65536 ) RND @ 31421 * ( RND*31421 ) 6927 + ( RND*31421+6926, mod 65536) DUP RND ! ( refresh he seed ) ; : CHOOSE ( n1 -- n2, a random number within 0 to n1 ) RANDOM UM* ( n1*random to a double product) SWAP DROP ( discard lower part ) ; ( in fact divide by 65536 ) \s Usage: To test the routine, type 100 CHOOSE . 100 CHOOSE . 100 CHOOSE .
\ Example 12. Square root : SQRT ( n1 -- n2, n2**2<=n1 ) 0 ( initial root ) SWAP 0 ( set n1 as the limit ) DO 1 + DUP ( refresh root ) 2* 1 + ( 2n+1 ) +LOOP ( add 2n+1 to sum, loop if ) ; ( less than n1, else done ) \s Usage: n sqrt .
3 fractions x y z : test Basic 10 let /{ x = ( 3 1 2 ) }/ 20 let /{ y = 1 3 7 }/ 30 let /{ z = x / y }/ 40 run z /3./ 50 end ;
\ Example 13. The Greatest Common Divisor (GCD) and Least Common Multiple (LCM) : GCD ( n1 n2 -- n3 ) BEGIN OVER MOD ?DUP WHILE SWAP REPEAT ABS ; : LCM ( n1 n2 -- n3 ) 2DUP GCD */ ABS ; \s Usage: n1 n2 GCD . n1 n2 LCM .
\ Example 14. The Fibonacci Sequence : Fib1 ( -- , print all Fibonacci numbers less than 50000 ) 1 1 ( two initial Fib numbers ) BEGIN OVER U. ( print the smaller number ) SWAP OVER + ( compute next Fib number ) DUP 50000 U> ( exit if number too large ) UNTIL ( else repeat ) 2DROP ( discard the numbers ) ; : Fib2 ( n -- , display all Fibonacci numbers smaller than n ) 1 ( initial number ) SWAP 1 ( set up range ) DO DUP U. ( print current number ) I ( the next Fibonacci number ) SWAP ( prepare the next to come ) +LOOP ( add current to index, if the ) ( repeat until sum>n ) U. ( print the last Fib ) ; \s Usage: To test the routines, try: Fib1 10000 Fib2
5 integers i n f(n) f(n+1) f(n+2) : Setn ( -- ) basic 10 print " n = " 20 inputi n 30 end ; : main basic 10 run Setn cr 20 let f(n) = 1 30 run f(n) . 40 let f(n+1) = 1 50 run f(n+1) . 60 let f(n+2) = f(n) + f(n+1) 70 if f(n+2) > n then 1000 80 run f(n+2) . 90 let f(n) = f(n+1) 100 let f(n+1) = f(n+2) 110 goto -60 1000 end ;
\ Fibonacci numbers 2 INTEGERS I N 0 BIGVARIABLE F(N) 10000 ALLOT 0 BIGVARIABLE F(N+1) 10000 ALLOT 0 BIGVARIABLE F(N+2) 10000 ALLOT : SetN ( -- ) BASIC 10 PRINT " Enter n =: " 20 INPUTI N 30 END ; : MAIN ( -- ) BASIC 10 RUN SetN 20 LET B{ F(N) = I>BIG ( 1 ) }B 30 LET B{ F(N+1) = I>BIG ( 1 ) }B 40 IF N < 3 THEN 100 50 FOR I = 1 TO N 60 LET B{ F(N+2) = F(N) + F(N+1) }B 70 LET B{ F(N) = F(N+1) }B 80 LET B{ F(N+1) = F(N+2) }B 90 NEXT I 100 PRINT " Fibonacci number( " ; N ; " )=" 110 RUN CR F(N) BIG. 120 END ; cr cr .( Usage: main ) cr main Enter n =: ? 10000 Fibonacci number( 10000 )= 2090 digits 54438373113565281338734260993750380135389184554695 :50 96702624771584120858286562234901708305154793896054 :100 11738226759780263173843595847511162414391747026429 :150 59169925586334117906063048089793531476108466259072 :200 75936789915067796008830659796664196582493772180038 :250 14411588410424809979846964873753371800281637633177 :300 81927941101369262750979509800713596718023814710669 :350 91264421477525447858767456896380800296226513311135 :400 99297627266794414001015758000435107774659358053625 :450 02461707918059226414679005690752321895868142367849 :500 59388075642348375438634263963597073375626009896246 :550 26687461120417398194048750624437098686543156268471 :600 86195620146126642232711815040367018825205314845875 :650 81719353352982783780035190252923951783668946766191 :700 79538847124410284639354494846144507787625295209618 :750 87597272889220768537396475869543159172434537193611 :800 26374392633731300589616724805173798630636811500308 :850 83967495871026195246313524474995052041983051871683 :900 21623283859794627245919771454628218399695789223798 :950 91219943177546970521613108109655995063829726125384 :1000 82420078971090547540284381496119304650618661701229 :1050 83288964352733750792786069444761853525144421077928 :1100 04597990456129812942380915605503303233891960916223 :1150 66987599227829231918966880177185755555209946533201 :1200 28446502371153715141749290913104897203455577507196 :1250 64542523286202201950609148358522388271101670843305 :1300 11699421157751512555102516559318881640483441295570 :1350 38825477521111577395780115868397072602565614824956 :1400 46053870028033131186148539980539703155572752969339 :1450 95860798503815814462764338588285295358034248508454 :1500 26446471681531001533180479567436396815653326152509 :1550 57112748041192819602214884914828438912417852017450 :1600 73055389287178579235094177433833315068982393544219 :1650 88805429332440371194867215543576548565499134519271 :1700 09891980266518456492782782721295764924023550759555 :1750 82056475693653948733176590002063731265706435097094 :1800 82649710038733517477713403319028105575667931789470 :1850 02411880309460403436295347199746139227479154973035 :1900 64126330742308240519999961015497846673404583268529 :1950 60388301120765629245998136251652347093963049734046 :2000 44510636530416363082366924225776146828846179184322 :2050 4793434406079917883360676846711185597501 =========1=========2=========3=========4=========5 12345678901234567890123456789012345678901234567890 =========(c) 2018 Copyright, Bottom Ruler========= OK
\ Example 15. ASCII Character Table : Printable ( n -- n , convert non-printable characters to spaces ) DUP 14 < ( 7-13 are special formatting ) IF DUP 6 > ( characters not displayable ) IF DROP 32 THEN ( substitute them by space ) THEN ; : HorizontalASCIItable ( -- ) CR CR CR 5 SPACES 16 0 DO I 4 .R LOOP ( show column header ) CR 16 0 DO ( do 16 rows ) CR I 16 * 5 .R ( print row header ) 16 0 DO ( print 16 characters in a row ) 3 SPACES J 16 * I + ( current character value ) Printable EMIT ( print it ) LOOP ( loop for next character ) LOOP ( loop for next row ) CR ; : ht horizontalasciitable ; : VerticalASCIItable ( -- ) CR CR CR 5 SPACES 16 0 DO I 16 * 4 .R LOOP ( show column headers ) CR 16 0 DO ( do 16 rows ) CR I 5 .R ( print row header ) 256 0 DO ( do 16 columns ) 3 SPACES J I + ( current character ) Printable EMIT 16 +LOOP ( skip 15 characters between columns) LOOP CR ; : vt verticalasciitable ; \s Usage: Type HorizontalASCIItable VerticalASCIItable or ht vt
1. LET 計算 2. FOR 就從 3. TO 做到 4. STEP 間隔 5. NEXT 配合 6. GOTO 跳到 7. IF 假如 8. THEN 前往 9. RUN 執行 10. PRINT 印出 11. END 結束
\ 全英文版程式 5 INTEGERS julianDate WhatDay Year Month Day : PrintWhatDay ( -- ) BASIC 10 IF WhatDay = 0 THEN 90 20 IF WhatDay = 1 THEN 110 30 IF WhatDay = 2 THEN 130 40 IF WhatDay = 3 THEN 150 50 IF WhatDay = 4 THEN 170 60 IF WhatDay = 5 THEN 190 70 IF WhatDay = 6 THEN 210 80 GOTO 1000 90 PRINT " This date is Sunday." 100 GOTO 1000 110 PRINT " This date is Monday." 120 GOTO 1000 130 PRINT " This date is Tuesday." 140 GOTO 1000 150 PRINT " This date is Wednesday." 160 GOTO 1000 170 PRINT " This date is Thursday." 180 GOTO 1000 190 PRINT " This date is Friday." 200 GOTO 1000 210 PRINT " This date is Saturday." 1000 END 1000 ; : MAIN ( -- ) BASIC 10 PRINT " Enter the date as Year Month Day: " CR 20 INPUTI Year , Month , Day 30 LET julianDate = ( 367 * Year ) + ( ( Month * 275 ) / 9 ) + Day + 1721029 - ( ( ( ( Month + 9 ) / 12 ) + Year ) * 7 / 4 ) - ( ( ( ( Year - ( ( Month + 9 ) / 12 ) ) / 100 ) + 1 ) * 3 / 4 ) 40 LET WhatDay = ( JulianDate + 1 ) MOD 7 50 RUN PrintWhatDay 60 END ; cr cr .( Usage: main ) cr \S \ 全中文版程式 5 個整數變數 星期餘數 儒略日 年 月 日 : 印出星期幾 ( -- ) 中文程式 10 假如 星期餘數 = 0 前往 90 20 假如 星期餘數 = 1 前往 110 30 假如 星期餘數 = 2 前往 130 40 假如 星期餘數 = 3 前往 150 50 假如 星期餘數 = 4 前往 170 60 假如 星期餘數 = 5 前往 190 70 假如 星期餘數 = 6 前往 210 80 跳到 1000 90 印出 " 這一天是星期天。" 100 跳到 1000 110 印出 " 這一天是星期一。" 120 跳到 1000 130 印出 " 這一天是星期二。" 140 跳到 1000 150 印出 " 這一天是星期三。" 160 跳到 1000 170 印出 " 這一天是星期四。" 180 跳到 1000 190 印出 " 這一天是星期五。" 200 跳到 1000 210 印出 " 這一天是星期六。" 1000 結束 ; : MAIN ( -- ) 中文程式 10 印出 " 請以 年 月 日 秩序輸入日期,數字之間必須空格 : " CR 20 輸入整數 年 , 月 , 日 30 計算 儒略日 = ( 367 * 年 ) + ( ( 月 * 275 ) / 9 ) + 日 + 1721029 - ( ( ( ( 月 + 9 ) / 12 ) + 年 ) * 7 / 4 ) - ( ( ( ( 年 - ( ( 月 + 9 ) / 12 ) ) / 100 ) + 1 ) * 3 / 4 ) 40 計算 星期餘數 = ( 儒略日 + 1 ) MOD 7 50 執行 印出星期幾 60 結束 ;
\ 計算任意階行列式值程式2009-08-23 INTEGER N 4 4 MATRIX AA : INPUT-DATA [[ N = 4 ]] {{ AA ( 1 1 ) = 1 }} {{ AA ( 1 2 ) = 2 }} {{ AA ( 1 3 ) = 3 }} {{ AA ( 1 4 ) = 4 }} {{ AA ( 2 1 ) = 2 }} {{ AA ( 2 2 ) = 3 }} {{ AA ( 2 3 ) = 4 }} {{ AA ( 2 4 ) = 1 }} {{ AA ( 3 1 ) = 3 }} {{ AA ( 3 2 ) = 4 }} {{ AA ( 3 3 ) = 1 }} {{ AA ( 3 4 ) = 2 }} {{ AA ( 4 1 ) = 4 }} {{ AA ( 4 2 ) = 1 }} {{ AA ( 4 3 ) = 2 }} {{ AA ( 4 4 ) = 3 }} ; INTEGER I INTEGER J INTEGER K INTEGER P INTEGER Q REAL A REAL D : SHOW-AA BASIC 10 FOR I = 1 TO 4 20 FOR J = 1 TO 4 30 PRINT { AA ( I J ) } 40 NEXT J 50 NEXT I 60 END ; : (DET) BASIC \ A program to evaluate a determinant by the leading diagonal method, \ using largest pivots. \ 10 RUN INPUT-DATA 20 LET { D = 1 } 30 FOR K = 1 TO ( N - 1 ) 40 LET P = K 50 LET Q = K 60 LET { A = ABS ( AA ( K K ) ) } 70 FOR I = K TO N 80 FOR J = K TO N 90 IF { ABS ( AA ( I J ) ) > A } THEN 110 100 GOTO 140 110 LET P = I 120 LET Q = J 130 LET { A = ABS ( AA ( I J ) ) } 140 NEXT J 150 NEXT I \ End of search for largest element. 160 IF P <> K THEN 180 170 GOTO 230 180 FOR J = K TO N 190 LET { A = AA ( P J ) } 200 LET { AA ( P J ) = AA ( K J ) } 210 LET { AA ( K J ) = NEGATE ( A ) } 220 NEXT J \ End of interchange of rows P and K. 230 IF Q <> K THEN 300 240 GOTO 270 250 FOR I = K TO N 260 LET { A = AA ( I Q ) } 270 LET { AA ( I Q ) = AA ( I K ) } 280 LET { AA ( I K ) = NEGATE ( A ) } 290 NEXT I \ End of interchange of columns Q and K. \ Largest element is now the pivot. 300 LET { D = D * AA ( K K ) } 310 IF { ABS ( D ) < 1.0e-10 } THEN 430 320 FOR I = K + 1 TO N 330 FOR J = K + 1 TO N 340 LET { A = AA ( K J ) * AA ( I K ) / AA ( K K ) } 350 LET { AA ( I J ) = AA ( I J ) - A } 360 IF { ABS ( AA ( I J ) ) < ABS ( A ) * 1.0e-10 } THEN 380 370 GOTO 390 380 LET { AA ( I J ) = 0 } 390 NEXT J 400 NEXT I \ End of reduction to upper triangular form. \ 405 PAUSE 410 NEXT K 420 LET { D = D * AA ( N N ) } 430 IF { ABS ( D ) > 1.0e-10 } THEN 450 440 LET { D = 0 } 450 LET { D = D } \ Determinant is got in D. \ 460 PRINT { D } 470 END ; : DET BASIC 10 RUN INPUT-DATA 20 IF N = 1 THEN 40 30 GOTO 60 40 LET { D = AA ( 1 1 ) } 50 GOTO 110 60 IF N = 2 THEN 80 70 GOTO 100 80 LET { D = AA ( 1 1 ) * AA ( 2 2 ) - AA ( 1 2 ) * AA ( 2 1 ) } 90 GOTO 110 100 RUN (DET) 110 PRINT { D } 120 END ; cr cr .( Usage : ) cr .( det ) cr
\ (28)ASCIIBox.f \ 以指定之字元,印出指定寬與高之長方形, : star 42 emit ; : top ( width -- ) 0 do star loop cr ; : bottom ( widty -- ) top ; : middle ( height -- ) star 2 - 0 do space loop star cr ; : box ( width height -- ) cr over top 2 - 0 do dup middle loop bottom ; page cr cr .( Usage Example: ) cr .( 40 10 box ) cr
\ pi.f \ 改寫自kforth之程式,只能run一次。故編譯完成後直接run。 \ 最後修正日期:20140114 \ Great Computer Language Shootout \ http://shootout.alioth.debian.org/ \ contributed by Albert van der Horst, Ian Osgood \ read NUM from last command line argument \ 0. argc @ 1- arg >number 2drop drop constant NUM \ 儲存計算結果的資料結構,靠這個常數來決定,編譯後就不能改,故用常數。 1300 constant NUM \ *** \ \ Arbitrary precision arithmetic \ A p-number consists of a count plus count cells, 2-complement small-endian \ \ Shorthand. : p>size ( pn -- size ) POSTPONE @ ; IMMEDIATE : p>last ( pn -- msb ) DUP p>size CELLS + ; : [I] POSTPONE I POSTPONE CELLS POSTPONE + ; IMMEDIATE \ Give sign of p : p0< ( p -- flag ) p>last @ 0< ; \ Copy a p-number to another buffer : pcopy ( src dst -- ) OVER p>size 1+ CELLS MOVE ; \ Check for overflow, extend the p-number if needed : ?carry ( carry p -- ) 2DUP p0< <> IF 1 OVER +! p>last ! ELSE 2DROP THEN ; \ In-place multiply by an unsigned integer : p* { n p -- } p p0< 0. ( sign dcarry ) p p>size 1+ 1 DO p [I] @ ( digit ) n UM* D+ SWAP ( carry digit ) p [I] ! 0 LOOP ROT n UM* D+ DROP p ?carry ; \ Ensure two p-numbers are the same size before adding 0 value signn \ *** 取消二度使用局部變數 : extend { p n -- } p p0< to signn \ { sign } \ *** sign to signn p p>size 1+ n p +! p p>size 1+ SWAP DO signn p [I] ! LOOP ; \ *** : ?extend ( p1 p2 -- p1 p2 ) OVER p>size OVER p>size - ?DUP IF DUP 0< IF >R OVER R> NEGATE ELSE OVER SWAP THEN extend THEN ; \ In-place addition of another p-number : p+ ?extend { src p -- } src p0< p p0< 0. ( sign sign dcarry ) p p>size 1+ 1 DO p [I] @ 0 D+ src [I] @ 0 D+ SWAP p [I] ! 0 LOOP DROP + + p ?carry ; \ add signs, check for overflow \ In-place subtraction of another p-number : p- ?extend { src p -- } src p0< p p0< 0. ( sign sign dcarry ) p p>size 1+ 1 DO p [I] @ 0 D+ src [I] @ 0 D- SWAP p [I] ! S>D LOOP DROP + + p ?carry ; \ add signs, check for overflow \ \ pi-spigot specific computation \ \ approximate upper limit on size required (1000 -> 1166) NUM 2* CELLS constant SIZE \ Current z transformation CREATE aq 1 , 1 , SIZE ALLOT CREATE ar 1 , 0 , SIZE ALLOT \ "as" identical zero and remains so CREATE at 1 , 1 , SIZE ALLOT \ Generate non-zero parts of next matrix ( K 4K+2 2K+1 ) VARIABLE KK \ *** K to KK : generate ( -- q r t ) 1 KK +! KK @ DUP 2* 1+ DUP 2* SWAP ; \ *** \ HERE is used as a temporary p-number \ Multiply z from the left : compose< ( bq br bt -- ) DUP at p* ar p* aq HERE pcopy HERE p* HERE ar p+ aq p* ; \ Multiply z from the right : compose> ( bt br bq -- ) DUP aq p* ar p* at HERE pcopy HERE p* HERE ar p- at p* ; \ Calculate z at point 3, leaving integer part and fractional part. \ Division is by multiple subtraction until the fractional part is \ negative. : z(3) ( -- n pfract )HERE aq OVER pcopy 3 OVER p* ar OVER p+ 0 BEGIN SWAP at OVER p- DUP p0< 0= WHILE SWAP 1+ REPEAT ; \ Calculate z at point 4, based on the result for point 3 \ and decide whether the integer parts are the same. : z(4)same? ( pfract -- flag ) aq OVER p+ p0< ; : pidigit ( -- nextdigit) BEGIN z(3) z(4)same? 0= WHILE DROP generate compose< REPEAT 1 OVER 10 * 10 compose> ; : .digit ( -- ) pidigit [CHAR] 0 + EMIT ; \ : .count ( n -- ) .\" \t:" 1 U.R CR ; \ *** : .count ( n -- ) 3 spaces ." :" 1 U.R CR ; \ Spigot n digits with formatting : spigot ( digits -- ) cr 0 \ *** BEGIN 50 + 2DUP > WHILE \ ***以下全原為10改成50 50 0 DO .digit LOOP DUP .count \ *** REPEAT 2DUP 50 - DO .digit LOOP OVER - SPACES .count ; \ *** (( : TypeCountingRuler ( -- ) \ *** 自建底標尺 cr ." =========1=========2=========3=========4=========5" cr ." 12345678901234567890123456789012345678901234567890" cr ." ========(c) 2014 Copyright, Counting Ruler========" cr ; )) NUM spigot TypeCountingRuler \ bye \ *** 取消bye
\ HeightWidth.f \ 20140210 \ 資料源自 Win32Forth 論壇 : HeightWidth ( -- ) SM_CYSCREEN call GetSystemMetrics \ 768 ok (y for the height) cr ." The height of screen is " . SM_CXSCREEN call GetSystemMetrics \ 1366 ok (x for the weight) cr ." The wide of screen is " . ; : main HeightWidth ; cr cr .( Usage: ) cr .( main ) cr