一百個例題 (76 ~ 80)
Ching-Tang Tseng
Hamilton, New Zealand
1 October 2024
\ (76)BisecFsqrt.f variable count \ full forth style fvariable n fvariable a fvariable b fvariable p : test ( f -- fsqrt ) 0 count ! fdup n f! a f! 0.0 E 0 b f! begin a f@ b f@ f- fabs 1. e -14 f> \ 以10Bytes/Float來算,設定便可以改為1.e-18,就與系統計算結果完全一致, \ 否則只能用1.e-14。 while a f@ b f@ f+ 2.0 e 0 f/ p f! a f@ fdup F* n f@ f- \ f(a)=a*a-n fdup f0= if fdrop a f@ exit then p f@ fdup f* n f@ f- \ f(p)=p*p-n fdup f0= if fdrop p f@ exit then f* f0> if p f@ a f! else p f@ b f! then 1 count +! repeat a f@ b f@ f+ 2. e 0 f/ dup -16 < if fround then ; \ 18 sigdigits ! : main 101 1 do cr i . ." count = " count @ . cr i . ." fsqrt = " i s>f fsqrt fs. cr i . ." bfsqrt = " i s>f test fs. loop ; main \s (( 9 reals n a b p fa fb fp eps ft : test1 ( f -- fsqrt ) 0 count ! fdup {{ n }} f! {{ a }} f! 0.E0 {{ b }} f! begin {{ fa = a * a - n }} {{ fb = b * b - n }} {{ eps = abs ( a - b ) - 1.E-15 }} eps f0> while {{ p = ( a + b ) / 2 }} {{ fp = p * p - n }} {{ ft = fa * fp }} ft f0> A if {{ a = p }} else {{ b = p }} then 1 count +! repeat cr ." count = " count @ . cr ." fsqrt1 = " {{ ft = ( a + b ) / 2 }} ft fs. cr ." fsqrt2 = " n fsqrt fs. ; \ need only n a b p ft : test2 0 count ! fdup {{ n }} f! {{ a }} f! 0.E0 {{ b }} f! begin {{ ft = abs ( a - b ) - 1.E-15 }} ft f0> while {{ p = ( a + b ) / 2 }} {{ ft = ( ( a * a ) - n ) * ( ( p * p ) - n ) }} ft f0> if {{ a = p }} else {{ b = p }} then 1 count +! repeat cr ." count = " count @ . cr ." fsqrt1 = " {{ ft = ( a + b ) / 2 }} ft fs. cr ." fsqrt2 = " n fsqrt fs. ; \ need only n a b p : test3 0 count ! fdup {{ n }} f! {{ a }} f! 0.E0 {{ b }} f! begin a b f- fabs 1.e-15 f> while {{ p = ( a + b ) / 2 }} a a F* n f- p p f* n f- f* f0> if {{ a = p }} else {{ b = p }} then 1 count +! repeat cr ." count = " count @ . cr ." fsqrt1 = " a b f+ 2.e0 f/ fs. cr ." fsqrt2 = " n fsqrt fs. ; ))
\ (77)hat.f \ Make an exclusive local array beside a word : hat ( n -- addr ) current @ swap cells - ; \ Usage and test demo \ Integer: compute 3*n1*n1+10*n1-7*n2 2 cells allot : test ( n1 n2 -- ) \ n2 to 2 hat n1 to 1 hat 2 hat ! 1 hat ! 3 1 hat @ dup * * dup cr . 10 1 hat @ * + dup cr . 7 2 hat @ * - cr . ; 1 cells allot : test2 ( n1 -- n2 ) 1 hat ! 1 hat @ dup * 2 * 1 hat @ -5 * - 10 + cr . ; \ Floatiing point: compute torque according to power and rotating speed \ ª«²zžÑµª p.183 , torque = hp / rpm \ 2 cells/fp 8 cells allot : torque ( hp rpm -- ) 6 hat f! 3 hat f! \ rpm to 4 hat, hp to 2 hat 3 hat f@ 550.e0 f* \ hp --> ft-lb/sec 6 hat f@ 2.e0 fpi f* f* 60.e0 f/ \ rpm --> rad/sec f/ cr ." torque = " fs. space ." lb-ft " ; 4 cells allot : torque2 ( hp rpm -- ) 550.e0 3 hat f! \ convert factore to 2 hat 2.e0 fpi F* f* 60.e0 f/ \ rpm --> rad/sec fswap 3 hat f@ f* fswap f/ cr ." torque = " fs. space ." lb-ft " ; \S \ for wina32 and lina64 \ (6). hat, fpi \ ************************************** \ Make an exclusive local array beside a word : hat ( n -- addr ) current @ >nfa @ swap 1+ cells - ; \ testing started from this point \ 1 cells allot \ : tt1 ( n -- ) \ 1 hat ! 10 30 * 5 + 1 hat @ /mod \ cr ." This is tt1." 3 spaces . . ; \ : tt2 ( -- ) \ cr ." This is tt2." ; \ : tt3 ( -- ) \ cr ." This is tt3." ; \ 2 cells allot \ : tt4 ( n1 n2 -- ) \ 2 hat ! 1 hat ! \ 10 1 hat @ * 2 hat @ + \ cr ." This is tt4." 3 spaces . ; \ 2+1-->3, 5+1-->6, 3 cells/fp \ 6 cells allot \ : tt5 ( r1 r2 -- ) \ 5 hat f! \ 2 hat f! \ 2 hat f@ 1.0 E 0 f* \ 5 hat f@ 3.0 E 0 f* \ f+ cr fs. ; 3.14159265358979328 E 0 fconstant fpi \ 6 cells allot \ : tt6 ( hp rpm -- ) \ 5 hat f! 2 hat f! \ rpm to 5 hat, hp to 2 hat \ 2 hat f@ 550. E 0 f* \ hp --> ft-lb/sec \ 5 hat f@ fpi fdup f+ f* 60. E 0 f/ \ rpm --> rad/sec \ f/ \ cr ." torque = " fs. space ." lb-ft " ; \ 3 cells allot \ : tt7 ( r -- ) \ 2 hat f! \ 10. E 0 fdup f* \ 2 hat f@ \ f/ cr fs. ; \ testing finished here \ ************************************** \ for gforth64 \ : hat ( n -- addr ) \ current @ >body swap 3 + cells - ; \ 3 cells allot \ : tt8 ( -- ) \ 1 1 hat ! 2 2 hat ! 3 3 hat ! \ 1 hat @ 2 hat @ + \ 3 hat @ + \ cr . ; \ execute tt8 get 6
\ (78) long dot /.. : (u.) ( u -- addr len ) 0 <# #s #> ; \ Maximum digits great than 253 characters. variable MaxDigits 400 MaxDigits ! : pad1 ( -- addr ) HERE 1024 + ; \ Big counted string at addr1 : BigCount ( addr1 -- addr2 len ) dup cell + swap @ ; \ Add string addr1 cnt to the big counted string addr2 : BigAppend ( addr1 len addr2 -- ) 2DUP 2>R BigCount CHARS + SWAP CMOVE 2R> DUP >R @ + R> ! ; \ Add one char to the big counted string addr : cBigAppend ( c addr -- ) dup >r BigCount + c! r@ @ 1+ r> ! ; : (/..) ( Numerator Denominator -- addr len ) dup 0= abort" Warning: /0 error! " pad1 256 0 fill 2dup 0< swap 0< xor 0< if 45 pad1 cBigAppend then \ - abs >r abs r> swap over /mod (u.) pad1 BigAppend \ integer part 46 pad1 cBigAppend \ . MaxDigits @ 1- 0 \ fraction part do over >r 10 um* r> um/mod (u.) pad1 BigAppend dup 0= if leave then loop 2drop pad1 BigCount ; variable 50c/l : RightSideMark ( -- ) 3 SPACES ." :" 50 50c/l +! base @ decimal 50c/l @ . base ! CR ; : BigTypeWithRightSideMark ( addr len -- ) 0 50c/l ! >r begin r@ 50 > while dup 50 type RightSideMark r> 50 - >r 50 + repeat r> type ; : 50cRuler ( -- ) cr ." =========1=========2=========3=========4=========5" cr ." 12345678901234567890123456789012345678901234567890" cr ." ========(c) 2014 Copyright, 50 chars Ruler========" cr ; : /.. ( Numerator Denominator -- ) (/..) cr BigTypeWithRightSideMark 50cRuler ;
\ (79) Double precision integer arithmetic. \ Revamped for ciforth from Dr. Tim Hendtlass, Real Time Forth, Swinburne University of Technology, 1993, P.62 \ 20170317 \ Multiply two double precision numbers to give a double precision product. : d- dnegate d+ ; \ : PICK 1+ CELLS DSP@ + @ ; \ : ?dnegate 0< if dnegate then ; \ With overflow check. : UD*C ( ud1 ud2 -- ud3 ) \ all numbers unsigned doubles dup >r rot dup >r >r over >r \ put a c c b on return stack >r swap dup >r \ put a d onto return stack um* \ b*d 0 r> r> um* d+ r> r> um* d+ \ offset 16 bits, add on a*d+b*c 0 r> r> um* d+ \ offset another 16 bits, add on a*c or 0<> abort" D* overflow" \ check for overflow ; \ Without overflow check. : UD* ( ud1 ud2 -- ud3 ) \ all numbers unsigned doubles rot >r over >r >r over >r \ put c b a d on return stack um* \ b*d = part of 32 bit answer r> r> * r> r> * + + \ a*d+b*c= addition to top 16 bits ; : D* ( d1 d2 -- d3 ) \ all numbers signed doubles dup >r dabs 2swap dup >r dabs \ #s +ve, keep info to work out final sign ud* \ get 32 bit answer. Change this to ud*c to get overflow c heck r> r> xor 0< if dnegate then \ r> r> xor ?dnegate \ work out and apply final sign ; \ More clear D* \ : D* ( d1 d2 -- d3 ) \ >r >r \ over r@ um* \ rot r> * + \ rot r> * + ; \ Division - ( U0 * 216 +U1 ) / (V0 * 216 + V1 ) = (A0 * 216 + A1 ) \ Use fast algorithm, remainder needs an additional 32 bit multiplication and subtraction. : T* ( ud un -- ut ) \ Unsigned double * unsigned single = unsigned triple dup rot um* >r >r \ high-part of answer to return stack um* 0 r> r> d+ \ get low-part,offset 16 bits,add high-part ; : T/ ( ut un -- ud ) \ Unsigned triple / unsigned single = unsigned double >r r@ um/mod swap \ divisor > r, divide top 16 bits, rem to top rot 0 r@ um/mod swap \ combine with next 16, divide these by divisor rot r> um/mod swap drop \ repeat for last 16 bits, lose final remainder 0 2swap swap d+ \ combine parts of answer to for final answer ; : U*/ ( ud un1 un2 -- ud2 ) \ ud * un1 / un2, triple intermediate product >r t* r> t/ ; : UD/ ( U1 U0 V1 V0 -- A1 A0) \ Unsigned 32 bit by 32 bit divide. No remainder dup 0= \ top 16 bits of divisor = 0? if swap t/ \ simple case, make it a triple, do / else \ more involved case dup 0 1 rot 1+ um/mod >r \ work out scaling factor,copy to r. (I did 65536. ==> 0 1) drop r@ t* drop >r >r \ scale denominator, move to return stack dup 0 r> r> 2dup >r >r u*/ d- \ calculate (U-U0*W1/W0) r> r> r> -rot nip u*/ \ multiply by (D/W0) nip 0 \ /2^16, make answer double then ; : D/MOD ( dn1 dn2 -- drem dquot ) \ Divide two signed double numbers 2 pick over xor >r \ work out sign of answer dabs 2swap dabs 2swap \ convert numbers to positive 2over 2over ud/ 2dup >r >r \ do the division, save copy of quotient ud* d- \ calculate the remainder r> r> r> 0< if dnegate then \ r> ?dnegate \ retrieve answer,apply final sign ; : D/ ( dn1 dn2 -- dquot ) \ Divide two signed doubles, no remainder 2 pick over xor >r \ work out sign of answer dabs 2swap dabs 2swap \ convert numbers to positive ud/ \ do the division r> 0< if dnegate then \ r> ?dnegate \ retrieve answer, apply final sign ;
\ (80-1)play music in wina forth : make-constant ( n adr -- ) BODY> >R R@ >DFA ! 'BL >CFA @ R> >CFA ! ; : LOAD-DLL: ( sc -- u ) CREATE $, DROP DOES> DUP >R $@ LOAD-DLL DUP R> make-constant ; : DLL-ADDRESS: ( sc xt -- adr ) CREATE , $, DROP DOES> DUP >R CELL+ $@ R@ @ EXECUTE DLL-ADDRESS DUP R> make-constant ; "kernel32.dll" LOAD-DLL: K32 "Beep" 'k32 DLL-ADDRESS: BBB : sing ( time frequency -- ) BBB call drop ; \ (64)tone.f \ 20160402 \ 基本原理只利用給音長及音頻後叫用Beep功能程式便可唱出單音來 \ 試用後效果顯示在XP環境中尚可,在W7環境中尾音被切除得很清楚,效果變差。 \ 選用192此值,係因可作為拍子設定之最小公倍數使用,以便都能除得整數。 \ 192 = 2*3*4*8 192 3 * VALUE Duration \ n1:Duration n2:Tone Frequency \ : sing ( n1 n2 -- ) CALL Beep drop ; : silence ( n1 -- ) MS ; : | ; immediate \ Get duration ( -- n1 ) : 4T Duration 4 * ; : 3T Duration 3 * ; : 2T Duration 2 * ; : 1T Duration ; : T/2 Duration 2 / ; : T/3 Duration 3 / ; : T/4 Duration 4 / ; : T/8 Duration 8 / ; : T/16 Duration 16 / ; \ Get tone frequency ( -- n2 ) \ 全面降八度時用,注意!每八度均成整數倍的關係。 \ : MDO 262 ; \ : MRE 294 ; \ : MMI 330 ; \ : MFA 349 ; \ : MSO 392 ; \ : MLA 440 ; \ : MSI 494 ; : MDO 523 ; : MRE 587 ; : MMI 659 ; : MFA 698 ; : MSO 784 ; : MLA 880 ; : MSI 988 ; \ Sing it ( n1 -- ) : Dl MDo sing ; : LDo MDo 2 / sing ; : HDo MDo 2 * sing ; : Re MRe sing ; : LRe MRe 2 / sing ; : HRe MRe 2 * sing ; : Mi MMi sing ; : LMi MMi 2 / sing ; : HMi MMi 2 * sing ; : Fa MFa sing ; : LFa MFa 2 / sing ; : HFa MFa 2 * sing ; : So MSo sing ; : LSo MSo 2 / sing ; : HSo MSo 2 * sing ; : La MLa sing ; : LLa MLa 2 / sing ; : HLa MLa 2 * sing ; : Si MSi sing ; : LSi MSi 2 / sing ; : HSi MSi 2 * sing ; : Waltzing-Matilda 1T SO T/2 SO T/2 SO 1T SO 1T MI 1T HDO T/2 HDO T/2 SI 1T LA 1T SO 1T SO T/2 SO T/2 SO 1T LA 1T SO 1T SO T/2 FA T/2 MI 1T RE T/2 Dl T/2 RE 1T MI 1T MI 1T RE 1T RE T/2 Dl T/2 RE T/2 MI T/2 Dl T/2 LLA T/2 LSI 1T Dl 1T LSO T/2 Dl T/2 MI 1T SO T/2 FA T/2 MI 1T RE T/2 RE T/2 RE 1T Dl ; : Jasmine 1T MI T/2 MI T/2 SO T/2 LA T/2 HDO T/2 HDO T/2 LA 1T SO T/2 SO T/2 LA 2T SO 1T MI T/2 MI T/2 SO T/2 LA T/2 HDO T/2 HDO T/2 LA 1T SO T/2 SO T/2 LA 2T SO 1T SO 1T SO 1T SO T/2 MI T/2 SO 1T LA 1T LA 2T SO 1T MI T/2 RE T/2 MI 1T SO T/2 MI T/2 RE 1T Dl T/2 Dl T/2 RE 2T Dl T/2 MI T/2 RE T/2 Dl T/2 MI 1T T/2 + RE T/2 MI 1T SO T/2 LA T/2 HDO 2T SO 1T RE T/2 MI T/2 SO T/2 RE T/2 MI T/2 Dl T/2 LLA 2T LSO 1T LLA 1T Dl 1T T/2 + RE T/2 MI T/2 Dl T/2 RE T/2 Dl T/2 LLA 2T LSO ; : I-am-a-little-bird 1T DL 1T DL 1T DL 1T T/2 + MI T/2 RE 1T DL 1T MI 1T MI 1T MI 1T T/2 + SO T/2 FA 1T MI 1T SO 1T FA 1T MI 3T RE 2T RE T/2 DL T/2 SI 1T DL 1T RE 1T MI 2T FA T/2 MI T/2 RE 1T MI 1T FA 1T SO T/2 SO T/2 FA 1T MI 1T RE 2T DL ; : Pocalicalina 1T SO T/2 HMI T/2 HMI T/2 HRE T/2 HRE 2T HDO 3T HMI ; : TEST 1 0 DO Waltzing-Matilda 2T silence Pocalicalina 2T silence Jasmine 2T silence I-am-a-little-bird 2T silence LOOP ;
\ Dmultiply.f \ In FSL_UTIL the following is defined: : d*1 ( d1 d2 -- dprod ) \ double multiply dup 3 pick xor >r dabs 2swap dabs udm* r> 0= IF exit ENDIF dxor 2swap dxor 1. UD+c >r \ ud1 ud2 carry1 -- ud1+ud2 carry2 2swap r> UD+c drop ; : d*2 ( d1 d2 -- dprod ) >r >r over r@ um* rot r> * + rot r> * + ; : d*3 ( d1 d2 -- d1*d2 ) >r swap >r 2dup um* 2swap r> * swap r> * + + ; : d*4 ( multiplicand . multiplier . -- product . ) 3 PICK * >R TUCK * >R UM* R> + R> + ;
\ FILEOP.F \ This file operation program works in Lina64 under CentOS7 \ Author: Ching Tang Tseng \ Date : 20160310, Hamilton, New Zealand WANT ALLOCATE \ -rw0rw0rw0 = 110110110b = 438d : all are R/W enable 438 CONSTANT R/W VARIABLE FileID VARIABLE Fptr VARIABLE Frem VARIABLE Flen VARIABLE Fsize 10240 Fsize ! \ (1)floating Fadr \ : Fadr PAD 4096 + ; \ (2)allocate Fadr ??? \ Fsize ALLOCATE DROP CONSTANT Fadr \ (3)fixed Fadr: 100 KB below EM \ EM HERE - . --> get 33425420 --> 33 MB free spaces : Fadr EM 102400 - ; : SetUpFptrFrem ( -- ) Fadr Fptr ! Flen @ Frem ! ; : (FILE.) ( -- addr len ) Fadr Flen @ ; : FileType ( -- ) CR (FILE.) TYPE ; : FileDump ( -- ) CR (FILE.) DUMP ; \ Beware! only a R/W attributed file can be manipulated \ S" Filename.f" GetFile = "Filename.f" GetFile : GetFile ( addr len -- ) Fadr Fsize @ 0 FILL R/W OPEN-FILE IF CR ABORT" OPEN-FILE error?" THEN FileID ! CR ." File ID is : " FileID @ . Fadr Fsize @ FileID @ READ-FILE IF CR ABORT" READ-FILE error?" THEN DUP Flen ! CR . ." Bytes has been read!" FileID @ CLOSE-FILE IF CR ABORT" CLOSE-FILE error!" THEN SetUpFptrFrem ; \ use PAD area create all blanks : NewFile ( addr len n -- ) Flen ! PAD Flen @ 32 FILL R/W CREATE-FILE IF CR ABORT" CREATE-FILE error!" THEN FileID ! PAD Flen @ FileID @ WRITE-FILE IF CR ABORT" WRITE-FILE error!" THEN CR Flen @ . ." Bytes has been written!" FileID @ CLOSE-FILE IF CR ABORT" CLOSE-FILE error!" THEN SetUpFptrFrem ; \ Beware! Flen must be set, before you WriteFile : SaveFile ( addr len -- ) R/W CREATE-FILE IF CR ABORT" CREATE-FILE error!" THEN FileID ! CR ." FileID is: " FileID @ . Fadr Flen @ FileID @ WRITE-FILE IF CR ABORT" WRITE-FILE error!" THEN CR Flen @ . ." Bytes has been written!" FileID @ CLOSE-FILE IF CR ABORT" CLOSE-FILE error!" THEN ; \ for simple testing usage: \ S" This is a simple test." SendText>F \ : SendText>F ( adr n -- ) \ DUP Flen ! Fadr SWAP MOVE ; \ Frem, Fptr are to be used for other testing.
\ PRINTstudy.f : main1 ( -- ) cr 73 65 do 13 1 do j emit i . loop cr loop ; 2 integers i j : main2 ( -- ) basic 10 run cr 20 for j = 65 to 72 30 for i = 1 to 12 40 run j emit i . 50 next i 60 run cr 70 next j 80 end ; \s main1 A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 B1 B2 B3 B4 B5 B6 B7 B8 B9 B10 B11 B12 C1 C2 C3 C4 C5 C6 C7 C8 C9 C10 C11 C12 D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 D11 D12 E1 E2 E3 E4 E5 E6 E7 E8 E9 E10 E11 E12 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 G1 G2 G3 G4 G5 G6 G7 G8 G9 G10 G11 G12 H1 H2 H3 H4 H5 H6 H7 H8 H9 H10 H11 H12 ok main2 A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 B1 B2 B3 B4 B5 B6 B7 B8 B9 B10 B11 B12 C1 C2 C3 C4 C5 C6 C7 C8 C9 C10 C11 C12 D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 D11 D12 E1 E2 E3 E4 E5 E6 E7 E8 E9 E10 E11 E12 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 G1 G2 G3 G4 G5 G6 G7 G8 G9 G10 G11 G12 H1 H2 H3 H4 H5 H6 H7 H8 H9 H10 H11 H12 ok
\ (74)SimpsonIntegration.f fvariable step defer method ( fn F: x -- fn[x] ) : left execute ; : right step f@ f+ execute ; : mid step f@ 2e f/ f+ execute ; : trap dup fdup left fswap right f+ 2e f/ ; : simpson dup fdup left dup fover mid 4e f* f+ fswap right f+ 6e f/ ; : set-step ( n F: a b -- n F: a ) fover f- dup 0 d>f f/ step f! ; : integrate ( xt n F: a b -- F: sigma ) set-step 0e 0 do dup fover method f+ fswap step f@ f+ fswap loop drop fnip step f@ f* ; \ testing similar to the D example : test ' is method ' 4 -1e 2e integrate f. ; : fn1 fsincos f+ ; : fn2 fdup f* 4e f* 1e f+ 2e fswap f/ ; 7 set-precision test left fn2 \ 2.456897 test right fn2 \ 2.245132 test mid fn2 \ 2.496091 test trap fn2 \ 2.351014 test simpson fn2 \ 2.447732 \S Numerical integration Write functions to calculate the definite integral of a function f(x) using all five of the following methods: rectangular left right midpoint trapezium Simpson's Your functions should take in the upper and lower bounds (a and b), and the number of approximations to make in that range (n). Assume that your example already has a function that gives values for f(x). Simpson's method is defined by the following pseudo-code: h := (b - a) / n sum1 := f(a + h/2) sum2 := 0 loop on i from 1 to (n - 1) sum1 := sum1 + f(a + h * i + h/2) sum2 := sum2 + f(a + h * i) answer := (h / 6) * (f(a) + f(b) + 4*sum1 + 2*sum2) Demonstrate your function by showing the results for: f(x) = x3, where x is [0,1], with 100 approximations. The exact result is 1/4, or 0.25. f(x) = 1/x, where x is [1,100], with 1,000 approximations. The exact result is the natural log of 100, or about 4.605170 f(x) = x, where x is [0,5000], with 5,000,000 approximations. The exact result is 12,500,000. f(x) = x, where x is [0,6000], with 6,000,000 approximations. The exact result is 18,000,000. \ (74-1)RectangleIntegration.f \ Author: Ching-Tang Tseng \ 20161107, Hamilton, Hamilton, NZ 9 reals a b h sum1 sum2 x f(x) f(a) f(b) 2 integers n i : function ( -- ) basic 10 let { f(x) = 1 / x } 20 end ; : Setting ( -- ) basic 10 let n = 1000 20 let { a = 1 } 30 let { b = 100 } 40 end ; \ All parts above are adjustable setting. \ All parts below are fixed. : SimpsonInit ( -- ) basic 10 run Setting 20 let { h = ( b - a ) / I>R ( n ) } 30 let { x = a + h / 2 } 40 run function 50 let { sum1 = f(x) } 60 let { sum2 = 0 } 70 let { x = a } 80 run function 90 let { f(a) = f(x) } 100 let { x = b } 110 run function 120 let { f(b) = f(x) } 130 end ; : Simpson ( -- ) \ 辛普森法 basic 10 run SimpsonInit 20 for i = 1 to n - 1 30 let { x = a + h * I>R ( i ) + h / 2 } 40 run function 50 let { sum1 = sum1 + f(x) } 60 let { x = a + h * I>R ( i ) } 70 run function 80 let { sum2 = sum2 + f(x) } 90 next i 100 print " Simpson integration = " ; { ( h / 6 ) * ( f(a) + f(b) + 4 * sum1 + 2 * sum2 ) } 110 end ; : L-Rectangle ( -- ) \ 長方形左側值法 basic 10 run Setting 20 let { h = ( b - a ) / I>R ( n ) } 30 let { x = a } 40 let { sum1 = 0 } 50 for i = 1 to n 60 run function 70 let { sum1 = sum1 + h * f(x) } 80 let { x = x + h } 90 next i 100 print " L-Rectangle integration = " ; { sum1 } 110 end ; : R-Rectangle ( -- ) \ 長方形右側值法 basic 10 run Setting 20 let { h = ( b - a ) / I>R ( n ) } 30 let { x = a } 40 let { sum1 = 0 } 50 for i = 1 to n 60 let { x = x + h } 70 run function 80 let { sum1 = sum1 + h * f(x) } 90 next i 100 print " R-Rectangle integration = " ; { sum1 } 110 end ; : M-Rectangle ( -- ) \ 長方形中間值法 basic 10 run Setting 20 let { h = ( b - a ) / I>R ( n ) } 30 let { x = a } 40 let { sum1 = 0 } 50 for i = 1 to n 60 let { x = x + h / 2 } 70 run function 80 let { sum1 = sum1 + h * f(x) } 90 let { x = x + h / 2 } 100 next i 110 print " M-Rectangle integration = " ; { sum1 } 120 end ; : Trapezoidal ( -- ) \ 梯形法 basic 10 run Setting 20 let { h = ( b - a ) / I>R ( n ) } 30 let { sum1 = 0 } 40 let { x = b } 50 run function 60 let { f(b) = f(x) } 70 let { x = a } 80 run function 90 let { f(a) = f(x) } 100 let { sum1 = h * ( f(b) + f(a) ) / 2 } 110 for i = 1 to n - 1 120 let { x = x + h } 130 run function 140 let { sum1 = sum1 + h * f(x) } 150 next i 160 print " Trapezoidal integration = " ; { sum1 } 170 end ; 18 sigdigits ! : main ( -- ) cr cr ." Integration of 1/x from 1 to 100 = Ln(100) " cr L-Rectangle R-Rectangle M-Rectangle Trapezoidal Simpson cr cr ." Ln(100) = " 100.0e0 fln f. cr ; main \S Integration of 1/x from 1 to 100 = Ln(100) L-Rectangle integration = 4.65499105751467615 R-Rectangle integration = 4.55698105751467615 M-Rectangle integration = 4.60476254867837518 Trapezoidal integration = 4.60598605751467615 Simpson integration = 4.60517038495714217 Ln(100) = 4.60517018598809137 ok
\ (75)高斯消去法解多元聯立一次方程式2009-08-22 INTEGER #ROW INTEGER ITEMP \ #ROW為方陣量,本例為3X3矩陣 INTEGER M INTEGER M1 INTEGER M2 REAL FTEMP 10 ARRAY Y 10 ARRAY X \ 矩陣上限宣告,暫設為10X10 10 10 MATRIX AA : 輸入數據 [[ #ROW = 3 ]] {{ AA ( 1 1 ) = 3 }} {{ AA ( 1 2 ) = 2 }} {{ AA ( 1 3 ) = 1 }} {{ AA ( 2 1 ) = 2 }} {{ AA ( 2 2 ) = 4 }} {{ AA ( 2 3 ) = 5 }} {{ AA ( 3 1 ) = 4 }} {{ AA ( 3 2 ) = 1 }} {{ AA ( 3 3 ) = 1 }} {{ Y ( 1 ) = 17 }} {{ Y ( 2 ) = 41 }} {{ Y ( 3 ) = 16 }} ; : 高斯處理 #ROW 1 DO [[ M = I + 1 ]] #ROW 1+ M DO #ROW 1+ M DO {{ AA ( J I ) = AA ( J I ) - ( AA ( K I ) * AA ( J K ) ) / AA ( K K ) }} LOOP {{ Y ( I ) = Y ( I ) - AA ( I J ) * Y ( J ) / AA ( J J ) }} LOOP M #ROW = IF {{ FTEMP = AA ( M M ) }} FTEMP F0= IF ." Equation disparity! " QUIT THEN THEN LOOP ; : 得到解答 [[ M = #ROW + 1 ]] #ROW 1+ 1 DO [[ M1 = M - I ]] {{ X ( M1 ) = Y ( M1 ) / AA ( M1 M1 ) }} [[ ITEMP = ( M - I ) - #ROW ]] ITEMP DUP 0> IF ." Trival! " QUIT THEN 0< IF #ROW 1+ 1 DO [[ M2 = M - I ]] {{ X ( M1 ) = X ( M1 ) - AA ( M1 M2 ) * X ( M2 ) / AA ( M1 M1 ) }} [[ ITEMP = ( M - I - 1 ) - ( M - J ) ]] ITEMP 0= IF LEAVE THEN LOOP THEN LOOP ; : 輸出答案 #ROW 1+ 1 DO {{ FTEMP = X ( I ) }} CR ." X( " I . ." )= " FTEMP F. LOOP ; : GAUSS 輸入數據 高斯處理 得到解答 輸出答案 ;
\ (66)RecursiveGCD.f : GCD ( n1 n2 -- n3 ) ?DUP IF SWAP OVER MOD RECURSE THEN ; variable TotalSum : n- ( n -- ) ?dup if dup TotalSum +! 1- recurse then ; : ss ( n -- ) 0 TotalSum ! n- TotalSum @ . ;
\ (67)exponential regression 2 integers n i 9 reals s1 s2 s3 s4 s5 x y a b 20 array xx 20 array yy : initialize basic 10 let { s1 = 0.0e0 } 20 let { s2 = s1 } 30 let { s3 = s1 } 40 let { s4 = s1 } 50 let { s5 = s1 } 60 end ; : InputData basic 10 let n = 9 20 let { xx ( 0 ) = 0.0e0 } :: { yy ( 0 ) = 291.0e0 } 30 let { xx ( 1 ) = 1.0e0 } :: { yy ( 1 ) = 324.0e0 } 40 let { xx ( 2 ) = 2.0e0 } :: { yy ( 2 ) = 571.0e0 } 50 let { xx ( 3 ) = 3.0e0 } :: { yy ( 3 ) = 830.0e0 } 60 let { xx ( 4 ) = 4.0e0 } :: { yy ( 4 ) = 1287.0e0 } 70 let { xx ( 5 ) = 5.0e0 } :: { yy ( 5 ) = 1975.0e0 } 80 let { xx ( 6 ) = 6.0e0 } :: { yy ( 6 ) = 2744.0e0 } 90 let { xx ( 7 ) = 7.0e0 } :: { yy ( 7 ) = 4599.0e0 } 100 let { xx ( 8 ) = 8.0e0 } :: { yy ( 8 ) = 6078.0e0 } 200 end ; : regression basic 10 run initialize InputData 20 for i = 0 to n - 1 30 let { x = xx ( i ) } 40 let { y = ln ( yy ( i ) ) } 50 let { s1 = s1 + x } 60 let { s2 = s2 + y } 70 let { s3 = s3 + x * x } 80 let { s4 = s4 + y * y } 90 let { s5 = s5 + x * y } 100 next i 110 let { b = ( i>r ( n ) * s5 - s2 * s1 ) / ( i>r ( n ) * s3 - s1 * s1 ) } 120 let { a = exp ( ( s2 - B * s1 ) / i>r ( n ) ) } 130 print " exponential regression: y = a * exp ( b * t ) " 140 run cr ." a = " a f. 150 run cr ." b = " b f. cr 160 let { y = a * exp ( b * 8.0e0 ) } 170 run cr ." y(8) = " y f. cr 180 let { y = a * exp ( b * 9.0e0 ) } 190 run cr ." y(9) = " y f. cr 200 end ; regression \s 程式的執行結果如下: exponential regression: y = a * exp ( b * t ) a = 254.72339048 b = 0.4020241052 y(8) = 6351.0221997 y(9) = 9493.8088062
\ factors.f (( '********************************************* '* Factorization of an integer number * '* ----------------------------------------- * '* Sample run: * '* * '* ? 394616 * '* * '* 2 2 2 107 461 * '* * '* ----------------------------------------- * '* Ref.: "Mathmatiques par l'informatique * '* individuelle (1) By H. Lehning * '* et D. Jakubowicz, Masson, Paris, * '* 1982" [BIBLI 06]. * '********************************************* )) 4 integers N D I L : test page basic 10 print " Enter integer number to be factorized " 20 inputi N \ 'Test if multiple of 2 40 let D = N mod 2 50 if D = 0 then 70 60 goto 100 70 print 2 80 let N = N / 2 90 goto -40 \ 'Test if multiple of 3 100 let D = N mod 3 110 if D = 0 then 130 120 goto 200 130 print 3 140 let N = N / 3 150 goto -100 \ 'Test of divisors 6i-1 and 6i+1 up to sqr(N) \ 'Prime numbers are of the form 6i-1 or 6i+1 200 let L = sqrt ( N ) + 1 210 for I = 6 to L step 6 220 let D = N mod ( I - 1 ) 230 if D = 0 then 250 240 goto 300 250 print ( I - 1 ) 260 let N = N / ( I - 1 ) 270 goto -220 300 let D = N mod ( I + 1 ) 310 if D = 0 then 330 320 goto 400 330 print ( I + 1 ) 340 let N = N / ( I + 1 ) 350 goto -300 400 next I 500 if N > 1 then 520 510 goto 600 520 print N 600 end ;
\ quotation.f : ends> r> ; : end >r ; immediate \ quotations: 局部副程式 : >EXEC >R ; \ for Win32Forth only : [: postpone ahead here -rot ends> postpone exit postpone then postpone literal ; immediate : ;] >r ; immediate \ or an alias of end : greet [: ." world" ;] ." hello" >exec ; \ for Win32forth \ execute ; \ for other forth
\ prime1.f 4 integers D N L I : test basic 10 print " Input an integer number N = " 20 inputi N 30 let D = N mod 2 40 if D = 0 then 220 50 let D = N mod 3 60 if D = 0 then 220 70 let L = sqrt ( N ) + 1 80 for I = 6 to L step 6 90 let D = N mod ( I - 1 ) 100 if D = 0 then 210 110 let D = N mod ( I + 1 ) 120 if D = 0 then 210 130 next I 140 print N ; " is a prime number." 150 goto 300 210 run 2drop 220 print N ; " is not a prime number." 300 end ; \ prime2.f 3 integers N I L : outrun 2drop ; : test PAGE BASIC 10 print " Input an integer number N = " 20 inputi N 30 if ( N mod 2 = 0 ) OR ( N mod 3 = 0 ) then 220 40 let L = sqrt ( N ) + 1 50 for I = 6 to L step 6 60 if ( N mod ( I - 1 ) = 0 ) OR ( N mod ( I + 1 ) = 0 ) then 210 70 next I 110 print " Yes, " ; N ; " is a prime number." 120 goto 300 210 run outrun 220 print " No, " ; N ; " is not a prime number." 300 end ; \S test Input an integer number N : ? 600 No, 600 is not a prime number. ok test Input an integer number N : ? 1999 Yes, 1999 is a prime number. ok \ prime3.f 6 integers N I J L C D : outrun 2drop ; : test PAGE BASIC 10 print " Input start and stop numbers C and D = " 20 inputi C , D 30 for J = C to D 40 let N = J 50 if ( N mod 2 = 0 ) OR ( N mod 3 = 0 ) then 220 60 let L = sqrt ( N ) + 1 70 for I = 6 to L step 6 80 if ( N mod ( I - 1 ) = 0 ) OR ( N mod ( I + 1 ) = 0 ) then 210 90 next I 110 print N 120 goto 220 210 run outrun 220 next J 300 end ; TEST \ prime4.f 6 integers N I J L C D : outrun 2drop ; : test PAGE BASIC 10 print " Input start and stop numbers C and D = " 20 inputi C , D 30 for J = C to D 40 let N = J 50 if N mod 2 = 0 then 220 60 if N mod 3 = 0 then 220 70 let L = sqrt ( N ) + 1 80 for I = 6 to L step 6 90 if N mod ( I - 1 ) = 0 then 210 100 if N mod ( I + 1 ) = 0 then 210 110 next I 120 print N 130 goto 220 210 run outrun 220 next J 300 end ; TEST \S testing range must be <= 2147483647 ( get it from -1 1 rshift . ) Input start and stop numbers C and D = ? 1999999000 2000000000 1999999003 1999999013 1999999049 1999999061 1999999081 1999999087 1999999093 1999999097 1999999117 1999999121 1999999151 1999999171 1999999207 1999999219 1999999271 1999999321 1999999373 1999999423 1999999439 1999999499 1999999553 1999999559 1999999571 1999999609 1999999613 1999999621 1999999643 1999999649 1999999657 1999999747 1999999763 1999999777 1999999811 1999999817 1999999829 1999999853 1999999861 1999999871 1999999873 1999999913 1999999927 1999999943 1999999973 \ prange1.f use \lina64\nfp2\f5102 6 integers N I J L A B : outrun 2drop ; : test BASIC 10 print " Input start and stop numbers A and B = " 20 inputi A , B 30 for J = A to B 40 let N = J 50 if ( N mod 2 = 0 ) OR ( N mod 3 = 0 ) then 220 60 let L = sqrt ( N ) + 1 70 for I = 6 to L step 6 80 if ( N mod ( I - 1 ) = 0 ) OR ( N mod ( I + 1 ) = 0 ) then 210 90 next I 110 print N 120 goto 220 210 run outrun 220 next J 300 end ; TEST \S Input start and stop numbers A and B = ? 1000000000001000 1000000000002000 1000000000001003 1000000000001027 1000000000001063 1000000000001089 1000000000001117 1000000000001209 1000000000001269 1000000000001293 1000000000001347 1000000000001371 1000000000001413 1000000000001491 1000000000001503 1000000000001551 1000000000001617 1000000000001623 1000000000001669 1000000000001741 1000000000001749 1000000000001819 1000000000001839 1000000000001867 1000000000001897 OK \ prange2.f use \lina64\nfp2\f5102 6 integers N I J L A B : outrun 2drop ; : test BASIC 10 print " Input start and stop numbers A and B = " 20 inputi A , B 30 for J = A to B 40 let N = J 50 if N mod 2 = 0 then 220 60 if N mod 3 = 0 then 220 70 let L = sqrt ( N ) + 1 80 for I = 6 to L step 6 90 if N mod ( I - 1 ) = 0 then 210 100 if N mod ( I + 1 ) = 0 then 210 110 next I 120 print N 130 goto 220 210 run outrun 220 next J 300 end ; TEST \S Input start and stop numbers A and B = ? 1000000000001000 1000000000002000 1000000000001003 1000000000001027 1000000000001063 1000000000001089 1000000000001117 1000000000001209 1000000000001269 1000000000001293 1000000000001347 1000000000001371 1000000000001413 1000000000001491 1000000000001503 1000000000001551 1000000000001617 1000000000001623 1000000000001669 1000000000001741 1000000000001749 1000000000001819 1000000000001839 1000000000001867 1000000000001897 OK \ prange3.f use \lina64\nfp2\f5102 7 integers N I J L A B C : outrun 2drop ; : test BASIC 10 print " Input start and stop numbers A and B = " 20 inputi A , B 30 LET C = 0 40 for J = A to B 50 let N = J 60 if N mod 2 = 0 then 220 70 if N mod 3 = 0 then 220 80 let L = sqrt ( N ) + 1 90 for I = 6 to L step 6 100 if N mod ( I - 1 ) = 0 then 210 110 if N mod ( I + 1 ) = 0 then 210 120 next I 130 LET C = C + 1 140 print N 150 goto 220 210 run outrun 220 next J 230 PRINT " total = " ; C 300 end ; TEST \S Input start and stop numbers A and B = ? 1000000000001000 1000000000002000 1000000000001003 1000000000001027 1000000000001063 1000000000001089 1000000000001117 1000000000001209 1000000000001269 1000000000001293 1000000000001347 1000000000001371 1000000000001413 1000000000001491 1000000000001503 1000000000001551 1000000000001617 1000000000001623 1000000000001669 1000000000001741 1000000000001749 1000000000001819
\ (61)Encrypte.f \ [---head---][lm|ln|---string---] : STRING ( lm -- ) CREATE 1 MAX MAXSTRING MIN DUP C, 0 C, ALLOT ( lm -- ) DOES> 1+ COUNT ; ( -- addr ln ) : S! ( addr1 cnt1 addr2 cnt2 -- ) DROP DUP 2 - C@ ROT MIN >R DUP 1- R@ SWAP C! R> CMOVE ; 80 STRING FILEPASSWORD \ password build here \ Usage: S" CTT20160310" FILEPASSWORD S! : EnterPassword ( -- ) CR ." Enter encrypte password : " CR QUERY 13 WORD COUNT FILEPASSWORD S! ; : EnterFileName ( -- ) CR ." Enter file name : " CR QUERY BL WORD COUNT GET-FILE ; : FILEENCRYPTE ( -- ) FLEN 0 DO I FADR + C@ I FILEPASSWORD NIP MOD FILEPASSWORD DROP + C@ XOR I FADR + C! LOOP ; : test ( -- ) EnterPassword EnterFileName CR CR FILETYPE FILEENCRYPTE CR CR FILETYPE FILEENCRYPTE CR CR FILETYPE ;
\ (62)Log2.f \ Lb(n) = Log2(n) , Lb(8)=3 means 8=2^3 \ ALb(n)= ALog2(n) = 2^n , ALb(3)=8 means 2^3=8 : Log2 ( n -- Log2[n] ) -1 SWAP BEGIN ?DUP WHILE SWAP 1+ SWAP 1 RSHIFT REPEAT ; : ALog2 ( n -- 2^n ) 1 SWAP 0 ?DO 2 * LOOP ;
\ (63)BackType.f \ 20160314 Hugh Aquilar posted on c.l.f. : backtype ( adr cnt -- ) over + 1- 2dup u< if do I c@ emit -1 +loop else 2drop then ; : $>pad ( adr cnt -- ) dup pad c! pad 1+ swap cmove ; s" this is a test." $>pad cr cr pad count type cr cr pad count backtype
\ (64)tone.f \ 20160402 \ 192 = 2*3*4*8 192 3 * VALUE Duration \ n1:Duration n2:Tone Frequency : sing ( n1 n2 -- ) CALL Beep drop ; : silence ( n1 -- ) MS ; : | ; immediate \ Get duration ( -- n1 ) : 4T Duration 4 * ; : 3T Duration 3 * ; : 2T Duration 2 * ; : 1T Duration ; : T/2 Duration 2 / ; : T/3 Duration 3 / ; : T/4 Duration 4 / ; : T/8 Duration 8 / ; : T/16 Duration 16 / ; \ Get tone frequency ( -- n2 ) : MDO 523 ; : MRE 587 ; : MMI 659 ; : MFA 698 ; : MSO 784 ; : MLA 880 ; : MSI 988 ; \ Sing it ( n1 -- ) : Dl MDo sing ; : LDo MDo 2 / sing ; : HDo MDo 2 * sing ; : Re MRe sing ; : LRe MRe 2 / sing ; : HRe MRe 2 * sing ; : Mi MMi sing ; : LMi MMi 2 / sing ; : HMi MMi 2 * sing ; : Fa MFa sing ; : LFa MFa 2 / sing ; : HFa MFa 2 * sing ; : So MSo sing ; : LSo MSo 2 / sing ; : HSo MSo 2 * sing ; : La MLa sing ; : LLa MLa 2 / sing ; : HLa MLa 2 * sing ; : Si MSi sing ; : LSi MSi 2 / sing ; : HSi MSi 2 * sing ; : Waltzing-Matilda 1T SO T/2 SO T/2 SO 1T SO 1T MI 1T HDO T/2 HDO T/2 SI 1T LA 1T SO 1T SO T/2 SO T/2 SO 1T LA 1T SO 1T SO T/2 FA T/2 MI 1T RE T/2 Dl T/2 RE 1T MI 1T MI 1T RE 1T RE T/2 Dl T/2 RE T/2 MI T/2 Dl T/2 LLA T/2 LSI 1T Dl 1T LSO T/2 Dl T/2 MI 1T SO T/2 FA T/2 MI 1T RE T/2 RE T/2 RE 1T Dl ; : Jasmine 1T MI T/2 MI T/2 SO T/2 LA T/2 HDO T/2 HDO T/2 LA 1T SO T/2 SO T/2 LA 2T SO 1T MI T/2 MI T/2 SO T/2 LA T/2 HDO T/2 HDO T/2 LA 1T SO T/2 SO T/2 LA 2T SO 1T SO 1T SO 1T SO T/2 MI T/2 SO 1T LA 1T LA 2T SO 1T MI T/2 RE T/2 MI 1T SO T/2 MI T/2 RE 1T Dl T/2 Dl T/2 RE 2T Dl T/2 MI T/2 RE T/2 Dl T/2 MI 1T T/2 + RE T/2 MI 1T SO T/2 LA T/2 HDO 2T SO 1T RE T/2 MI T/2 SO T/2 RE T/2 MI T/2 Dl T/2 LLA 2T LSO 1T LLA 1T Dl 1T T/2 + RE T/2 MI T/2 Dl T/2 RE T/2 Dl T/2 LLA 2T LSO ; : I-am-a-little-bird 1T DL 1T DL 1T DL 1T T/2 + MI T/2 RE 1T DL 1T MI 1T MI 1T MI 1T T/2 + SO T/2 FA 1T MI 1T SO 1T FA 1T MI 3T RE 2T RE T/2 DL T/2 SI 1T DL 1T RE 1T MI 2T FA T/2 MI T/2 RE 1T MI 1T FA 1T SO T/2 SO T/2 FA 1T MI 1T RE 2T DL ; : Pocalicalina 1T SO T/2 HMI T/2 HMI T/2 HRE T/2 HRE 2T HDO 3T HMI ; : TEST 1 0 DO Waltzing-Matilda 2T silence Pocalicalina 2T silence Jasmine 2T silence I-am-a-little-bird 2T silence LOOP ; \s The following table shows the relationship of notes and their frequencies in one octave. _______________________________________________________ C D E F G A B Dl Re Mi Fa So La Si 261.63 293.66 329.63 349.23 392.00 440.00 493.88 523.25 587.33 659.26 698.46 783.99 880.00 987.77 ------------------------------------------------------- By doubling or halving the frequence, the coinciding note values can be estimated for the preceding and following octaves. \ (64-1)play music in wina forth : Z ( sc -- adr) 0 , DROP ; : make-constant ( n adr -- ) BODY> >R R@ >DFA ! 'BL >CFA @ R> >CFA ! ; : LOAD-DLL: ( sc -- u ) CREATE $, DROP DOES> DUP >R $@ LOAD-DLL DUP R> make-constant ; : DLL-ADDRESS: ( sc xt -- adr ) CREATE , $, DROP DOES> DUP >R CELL+ $@ R@ @ EXECUTE DLL-ADDRESS DUP R> make-constant ; "kernel32.dll" LOAD-DLL: K32 "Beep" 'k32 DLL-ADDRESS: BBB : sing ( time frequency -- ) BBB call drop ; \ (64-2)FasmForth64Tone.F \ REQUIRE API_2: lib\WAPI.4 \ REQUIRE API_2: WAPI.4 : DLL_CREATE CREATE PARSE-NAME FILE-BUFF ASCII-Z DLL_S DUP 0= ABORT" api unavailable" , ; : API_0: DLL_CREATE DOES> @ API_0 ; : API_1: DLL_CREATE DOES> @ API_1 NIP ; : API_2: DLL_CREATE DOES> @ API_2 NIP NIP ; : API_3: DLL_CREATE DOES> @ API_3 NIP NIP NIP ; : API_4: DLL_CREATE DOES> @ API_4 NIP NIP NIP NIP ; : API_5: DLL_CREATE DOES> @ API_5 NIP NIP NIP NIP NIP ; \ CR .( LIB LOAD=) S" KERNEL32.DLL" DROP DLL_L DUP H. \ DUP 0= [IF] .( KERNEL32.DLL LOAD ERROR) ABORT [THEN] S" KERNEL32.DLL" DROP DLL_L CONSTANT KERNEL32DLL \ Get API Beep KERNEL32DLL API_2: Beep Beep : sing ( duration freqency -- ) Beep DROP ;
: tone ( time frequency -- ) CALL Beep drop ; \ morse demonstation begins here 880 constant freq \ 440 --> 880, value --> constant 45 constant adit \ 1 dit will be 45 ms, value --> constant : ns 4 * ; \ convert adit to duration value, without nano second meaning : dit_dur adit ns ; : dah_dur adit 3 * ns ; : wordgap adit 5 * ns ; : off_dur adit 2/ ns ; : lettergap dah_dur ; : sound ( duration -- ) freq tone ; : silence ( duration -- ) 0 tone ; : MORSE-EMIT ( char -- ) \ send morse and echo to console dup bl = \ bl = blank = 32 if wordgap silence drop else PAD C! \ write char to buffer PAD 1 EVALUATE \ evaluate 1 character lettergap silence \ pause for correct sounding morse code then ; : BOUNDS ( ADDR LEN -- Last Init ) OVER + SWAP ; : TRANSMIT ( ADDR LEN -- ) CR \ newline, BOUNDS \ convert loop indices to address ranges DO I C@ dup emit \ dup and send char to console MORSE-EMIT \ send the morse code LOOP ; : . ( -- ) dit_dur sound off_dur silence ; : - ( -- ) dah_dur sound off_dur silence ; \ define morse letters as Forth words. They transmit when executed : A . - ; : B - . . . ; : C - . - . ; : D - . . ; : E . ; : F . . - . ; : G - - . ; : H . . . . ; : I . . ; : J . - - - ; : K . - . ; : L . - . . ; : M - - ; : N - . ; : O - - - ; : P . - - . ; : Q - - . - ; : R . - . ; : S . . . ; : T - ; : U . . - ; : V . . . - ; : W . - - ; : X - . . - ; : Y - . - - ; : Z - - . . ; : 0 - - - - - ; : 1 . - - - - ; : 2 . . - - - ; : 3 . . . - - ; : 4 . . . . - ; : 5 . . . . . ; : 6 - . . . . ; : 7 - - . . . ; : 8 - - - . . ; : 9 - - - - . ; : ' - . . - . ; : \ . - - - . ; : ! . - . - . ; : ? . . - - . . ; : , - - . . - - ; : / . . . - . - ; ( SK means end of transmission in int'l Morse code) : . . - . - . - ; S" CQ CQ CQ DE VE3CFW VE3CFW / " TRANSMIT
\ (56)Beers.f \ 一瓶啤酒 2 元,兩個空瓶可以換一瓶啤酒,四個瓶蓋可以換一瓶啤酒。 \ 請問 n 元可以喝到幾瓶啤酒? \ t : 可得啤酒總數 \ r : 循環回收次數 \ a : 暫態計算結果 \ b : 空瓶數 \ c : 瓶蓋數 5 values t r a b c \ 只對偶數的起始費用有效,奇數元必須先扣除1元 : Init ( n -- ) 0 to r 2 /mod dup dup to t to b to c if cr ." 1 dollar redundant." then ; : Recycle ( -- ) 0 to a b 2 /mod +to a to b c 4 /mod +to a to c a +to t a +to b a +to c ; : main ( n -- ) Init begin 1 +to r Recycle a 0= until cr ." Total = " t . cr ." 回收次數 = " r . cr ." 剩餘空瓶數 = " b . cr ." 剩餘瓶蓋數 = " c . ; \ 經過分析可得下列結論 \ 啤酒的純脆價值為每瓶0.5元,每個空瓶為1元,每個瓶蓋為0.5元。 \ 因此,若以 n 元購此啤酒,兌換到最後,必定只剩 1 個空瓶,3 個瓶蓋。 \ 以此結論,各樣東西的價值不會無中生有,也不會無中消失,故 \ ( n - 1 - ( 3 * 0.5 ) ) / 0.5 便為可獲得之所有啤酒瓶數的等效金錢。 \ 但此式只對偶數的起始金錢有效,奇數金錢,一開始就必須結餘1元,不列入計算。 \ 例如:花 23元,可獲得 ((23-1)-2.5) / 0.5 = 39 (瓶) \S 10 main Total = 15 回收次數 = 6 剩餘空瓶數 = 1 剩餘瓶蓋數 = 3 ok 23 main 1 dollar redundant. Total = 39 回收次數 = 9 剩餘空瓶數 = 1 剩餘瓶蓋數 = 3 ok 57 main 1 dollar redundant. Total = 107 計回收次數 = 13 剩餘空瓶數 = 1 剩餘瓶蓋數 = 3 ok 100 main Total = 195 回收次數 = 15 剩餘空瓶數 = 1 剩餘瓶蓋數 = 3 ok
\ LessThan.f \ How many integers n satisfy this inequality? \ ( n^2 - 2 ) ( n^2 - 20 ) < 0 \ Can you find them all? \ use FORTH code solve it as following: : main ( n -- ) dup dup * dup >r 2 - r> 20 - * 0 < if cr . else drop then ; : TellMe ( to from -- ) do I main loop ; \S \ Usage: 100 -100 TellMe -4 -3 -2 2 3 4 ok
\ (58)PadHere.f \ 20151201 \ 利用 PAD, HERE, Return Stack存放變數的技巧 \ 只適用於 4 個數字時使用 : test ( 1 2 3 4 -- 4 3 2 1 ) here ! pad ! swap >r >r here @ pad @ r> r> ; \ 均適用於整數、實數、複數,故一個單元就取 4 個 cells \ : [PAD] ( n -- addr ) \ 4 * cells pad + ; \ 比較理想的設計為包括也考慮 bytes/float = 10 的情況 \ 如果記憶體用量根本不是問題時,每一 單元乾脆就取 80 Bytes.字串也能使用 : [PAD] ( n -- addr ) 80 * PAD aligned + ; : [PAD]N.S ( from to -- ) CR 1+ SWAP DO I [PAD] @ . LOOP ; : [PAD]F.S ( from to -- ) CR 1+ SWAP DO I [PAD] F@ FS. LOOP ; : [PAD]Z.S ( from to -- ) CR 1+ SWAP DO I [PAD] Z@ Z. LOOP ; : ntest ( 1 2 3 4 -- 4 3 2 1 ) CR .S 1 [pad] ! 2 [pad] ! 3 [pad] ! 4 [pad] ! 1 4 [PAD]N.S 1 [pad] @ 2 [pad] @ 3 [pad] @ 4 [pad] @ CR .S ABORT ; : ftest ( f: 1e 2e 3e 4e -- 4e 3e 2e 1e ) CR F.S 1 [pad] f! 2 [pad] f! 3 [pad] f! 4 [pad] f! 1 4 [PAD]F.S 1 [pad] f@ 2 [pad] f@ 3 [pad] f@ 4 [pad] f@ CR F.S ; \ Usage: \ 1 2 3 4 ntest \ 1e 2e 3e 4e ftest
\ (59)LastDigit.f (( https://brilliant.org/practice/level-2-3-operations/ What is the last digit of this sum? Find the last digit when 1^1 + 2^2 + 3^3 + .... + 9^9 + 10^10 is written out as an integer. )) 6 integers i j k l p s : demo1 ( n -- ) \ maximum less than 11 [[ j ]] ! basic 10 let k = 0 20 for i = 1 to j 30 print " " ; i ; " ^ " ; i ; " = " , i ^ i 40 let k = k + i ^ i 50 next i 60 print " Sum( " ; j ; " ) = " , k 70 end ; : demo2 ( n -- ) \ maximum less than 11 [[ j ]] ! basic 10 for k = 1 to j 20 let s = 1 30 for i = 1 to k 40 let s = s * k 50 next i 60 print s 70 next k 80 end ; : test ( n -- ) \ maximum can up to very huge [[ j ]] ! \ 最高方次為 j (highest power is j) basic 10 let s = 0 20 for k = 1 to j \ k 表從 1 開始,做到最高方次 j (k terms) 30 let l = 1 40 for i = 1 to k 50 let l = ( l * k ) mod 10 \ 每自乘一次均只留單個尾數 l (last digit) 60 next i 80 let s = s + l \ s 為所有尾數之和 (summation of last digits) 90 next k 100 let s = s mod 10 \ 取得尾數總和之最後一位尾數 110 run s . 120 end ; : main ( -- ) basic 10 for p = 0 to 20 \ 算出最高方次 p(power) 為從 0 到 100 的所有結果 20 print " Last power = " ; p ; " last digit is " 30 run p test 40 next p 50 end ; \ page main \ 執行 main 後,結果顯示,0 到 9 都有可能。 \S ok 10 demo1 1 ^ 1 = 1 2 ^ 2 = 4 3 ^ 3 = 27 4 ^ 4 = 256 5 ^ 5 = 3125 6 ^ 6 = 46656 7 ^ 7 = 823543 8 ^ 8 = 16777216 9 ^ 9 = 387420489 10 ^ 10 = 1410065408 ----> overflow Sum( 10 ) = 1815136725 ok ching@ching-H81M-S2H:~$ cd lina64 ching@ching-H81M-S2H:~/lina64$ ./f5082 AMDX86 ciforth 5.2.1 include lastdigit.f I : ISN'T UNIQUE J : ISN'T UNIQUE OK 15 demo1 1 4 27 256 3125 46656 823543 16777216 387420489 10000000000 285311670611 8916100448256 302875106592253 11112006825558016 437893890380859375 OK
\ (60)SquarBitServey.f : test ( n -- ) dup dup * >r >r cr decimal r@ 10 .r binary r> 20 .r cr decimal r@ 10 .r binary r> 20 .r decimal ; : main ( -- ) page 11 0 do cr i test cr loop ;
\ Simple Floating-Point Output \ Revision 2013-10-29 \ This simple floating-point output package has features found in more comprehensive implementations yet \ is remarkably compact and portable. Based on code and algorithm from Forth Inc. \ SFPOUT.F \ \ Simple Floating Point Output \ \ Main words: \ \ (F.) (FS.) (FE.) F.R FS.R FE.R F. FS. FE. \ FDP PLACES \ \ This package should function correctly on any Forth \ system with the following limitations: \ \ - Don't attempt to output non-numbers such as NANs \ or INFs as it will enter an infinite loop. \ - Floating-point strings are limited to the size of \ the system's pictured numeric output buffer. \ \ History: \ 131029 Fix (F.) to use FDP. Add F. FS. FE. PLACES FORTH DEFINITIONS DECIMAL \ 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 ; \ Variable controlling trailing decimal point display. \ Default (ON) is to always display decimal point. VARIABLE FDP 1 FDP ! : 10^n ( r1 n -- r2 ) 0 ?DO 10.E F* LOOP ; : #.n ( r1 n -- r2 ) 0 ?DO #. LOOP ; VARIABLE rscale 1 rscale ! FVARIABLE rstep 10.E rstep F! VARIABLE fdpl 4 fdpl ! \ 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 F@ F< 0= WHILE rstep F@ F/ R> rscale @ + >R REPEAT BEGIN FDUP 1.0E F< WHILE rstep F@ F* R> rscale @ - >R REPEAT THEN 2R> ; \ Convert fixed-point : fcvt ( r n -- ) >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 exponential \ notation with n places right of the decimal point. : (e.) ( r n scale step -- c-addr u ) rstep F! 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 F@ F< 0= IF ( overflow) rstep 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 fcvt ; \ Convert real number r to string c-addr u in scientific \ notation with n places right of the decimal point. : (FS.) ( r n -- c-addr u ) 1 10.E (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 (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. : (FE.) ( r n -- c-addr u ) 3 1000.E (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 (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.) ( r n -- c-addr u ) 0 MAX DUP >R 10^n <#. ( round) R> fcvt ; \ 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 ( r n u -- ) >R (F.) R> OVER - SPACES TYPE ; \ Set decimal places control for F. FS. FE. : PLACES ( n -- ) fdpl ! ; : F. ( r -- ) fdpl @ 0 F.R SPACE ; : FS. ( r -- ) fdpl @ 0 FS.R SPACE ; : FE. ( r -- ) fdpl @ 0 FE.R SPACE ; [DEFINED] DXFORTH [IF] behead 10^n (e.) [THEN] \ end
\ elimit.f integer i 2 reals x n 1000 array x : x(n) BASIC 10 for i = 1 to 1000 20 let { n = i>r ( i ) } 20 let { x ( i ) = ( 1 + 1 / ln ( n ) ) ^ n } 30 next i 40 end ; : main BASIC 10 run x(n) 20 print " x( 1) = " ; { x ( 1 ) } 30 print " x( 10) = " ; { x ( 10 ) } 40 print " x( 100) = " ; { x ( 100 ) } 50 print " x(1000) = " ; { x ( 1000 ) } 60 end ; \s c file: elimit.f c double precision x dimension x(1000) c print * print *,' Slowly converging sequence for irrational number e' print *,' Section 1.2, Kincaid-Cheney' print * c do 2 n=1,1000 x(n) = (1.0d0 + 1.0d0/dble(n))**n 2 continue c print *,' 1, x(1) =',x(1) print *,' 10, x(10) =',x(10) print *,' 30, x(30) =',x(30) print *,' 50, x(50) =',x(50) print *,' 1000, x(1000) =',x(1000) print *,' exp(1.0) =',exp(1.0d0) print * print *,' error =',abs(x(1000) - exp(1.0d0)) c stop end
\ 2**(-n) (( c c Second Edition c Numerical Analysis: c The Mathematics of Scientific Computing c D.R. Kincaid and E.W. Cheney c Brooks/Cole Publ., 1996 c ISBN 0-534-33892-5 c COPYRIGHT (c) 1996 c c Section 2.1 c c Computing an approximate value of machine precision c c c file: epsi.f c print * print *,' Approximate value of machine precision' print *,' Section 2.1, Kincaid-Cheney' print * print *,' n computed 2**(-n)' c s = 1.0 c do 2 k=1,100 s = 0.5*s t = s + 1.0 if (t .le. 1.0) then s = 2.0*s t = 1.0/2.0**(k-1) print 3,k-1,s,t stop endif 2 continue c 3 format (i3,2x,2(e13.6,2x)) stop end )) 2 integers k k-1 2 reals s t 20 sigdigits ! : main BASIC 10 let { s = 1 } 20 for k = 1 to 100 30 let { s = 0.5 * s } 40 let { t = s + 1 } 50 if { t <= 1 } then 100 60 let { s = 2 * s } 70 let k-1 = k - 1 80 let { t = 1 / ( 2 ^ i>r ( k-1 ) ) } 90 print " " ; k-1 , { s , t } 100 next k 110 end ; : main2 basic 10 for k = 1 to 100 20 let { t = 1 / ( 2 ^ i>r ( k ) ) } 30 print " " ; k , { t } 40 next k 50 end ;
\ (54)nCrAndnPr.f \ 二項式的係數可以應用 nCr 求得 \ 用法:執行 10 5 nCr big. 可得 (1+x)^10 之第 5 項係數為 252 \ 注意!使用 n r nCr 或 n r nPr 時 r 必須 >0 且 r 不得為 0 \ 使用 n r nCrOrg 則 r 可以 = 0 \ 定義 :: nCr = n! / ( (n-r)! * r! ) :: nPr = n! / (n-r)! 1 bigvariable n! 20000 allot 1 bigvariable (n-r)! 20000 allot 1 bigvariable r! 20000 allot 1 bigvariable d 20000 allot 3 integers k n r : nCrOrg ( n r -- addr ) \ get addr of big d, r>=0 [[ r ]] ! [[ n ]] ! basic 10 LET b{ n! = big1 }b :: b{ (n-r)! = big1 }b :: b{ r! = big1 }b :: b{ d = big1 }b 20 FOR k = 1 TO n 30 LET b{ n! = n! * i>big ( k ) }b 40 NEXT k 50 FOR k = 1 TO n - r 60 let b{ (n-r)! = (n-r)! * i>big ( k ) }b 70 next k 80 for k = 1 to r 90 let b{ r! = r! * i>big ( k ) }b 100 next k 110 let b{ d = n! / ( (n-r)! * r! ) }b \ 120 run d big. 130 end d \ big. ; : nCr ( n r -- addr ) \ get addr of big d, r>0, r=/=0 [[ r ]] ! [[ n ]] ! basic 10 LET b{ n! = big1 }b :: b{ r! = big1 }b :: b{ d = big1 }b 20 FOR k = n - r + 1 TO n 30 LET b{ n! = n! * i>big ( k ) }b 40 NEXT k 50 FOR k = 1 TO r 60 let b{ r! = r! * i>big ( k ) }b 70 next k 80 let b{ d = n! / r! }b \ 90 run d big. 100 end d \ big. ; : nPr ( n r -- addr ) \ get addr of big d, r>0, r=/=0 [[ r ]] ! [[ n ]] ! basic 10 let b{ d = big1 }b 20 for k = n - r + 1 to n 30 let b{ d = d * i>big ( k ) }b 40 next k \ 50 run d big. 60 end d \ big. ; variable m : test ( n -- ) m ! page m @ 1+ 0 do cr ." Term ( " m @ . ." , " I . ." ):" m @ I nCrOrg big. cr loop ; \ Usage: 100 test \S ok 10 5 nCr big. 3 digits 252 ok 49 6 nCr big. 8 digits 13983816 ok 200 100 nCr big. 59 digits 90548514656103281165404177077484163874504589675413 336841320 ok 10000 5000 nCr big. 3009 digits 15917902635324389483375972736415211886530058374576 14550428319103517772637120095798663262853944222217 74335859829932262055804632908708020739850879872195 95848962041757866458580184099587512068914331597813 53174051453473199670521394502538477277336008312053 78448823951274321755502883180927364644281795459349 36890023546288054736628292721322091972680306215783 97698552486834508478688949946112620233602352989894 58928488427591110374321646235202929095545845304023 49292778714312397841036259290830007542173305536549 24253683062815307296533408892556506908751506476159 44622376204326852230062678211259375951657115342848 24533318106868409528400428469950435925781799643074 13894226494475866262818621837575412803625468813885 44759125956185871468454381861463662350728468211441 65546574399328400579417002212869168618937974722788 62022397883728976020496710189761906178593058261688 08117556117796960379809282174855477301204105813490 54627159851188661377744154110563694305682072524481 94310502564874945796288376042950798729141780053010 24149340722579759834860211640098545723183096418633 68889831214559707246945445665178908193538606256602 93683165225062715958242340375627937873328871136143 52737971292965638066368798136853809235306441396478 97981427998980441958797431047888940127197101544121 68400963446529395285243067100038066963076992572201 04426311836533049067512198270012436774453339363870 02281179253561881400957197317504497933395227608620 35738939329776832343771264615030169561499601195082 06705891127875644018328002477885570580594271739655 61724727970366569861808080196554123575656465556543 39707955136421179968234829408914932867170470389361 58996297545140449708716896119990505242038078767450 45086398524630406716702026949125606462058300176130 06222847575106625661061937714355872185378096200269 13816305961756296827876710659465040754767228071475 82168701916632425820168589328145494184963321901025 03263315943618316059553444266801897513519884512933 06946591872301020473208721181284611163964165765568 93394074097665692587872816840693520731443017872513 61780157927471147290158311709071711945782984829441 64359840658473384707719418659651955333974514346503 81761619761261615704035455946677454877741276547147 86635414188001119626029573352659456865843697213096 86983612640564990207924247805354140963069566603071 19593156917262680235151820878651554693737963876050 46437155479530978766508167970001769266592869187570 94175117347665748132703540903393455409827319346571 30920200412827961158882797284732350179796997256267 19728263470177566063313040160755515205233184045927 56797612244679324194846919392918520452394577675953 32686906744319279375609565885643212422852240351665 84543197040090546963296363638177915596412050056857 02690372838060388519713403611629040056633420468941 76159382456860877054526939045603888375597321562922 27663423267910309912054892793591354641456968021307 92488795541350742383065293811197486421347908348956 55794152699977683783414705903919974789150191636363 96775919453875351801524980522104507017055088380935 44209022455222930021060372371375638589078163387440 553649120 ok
\ (55)BinomialTable.f : nCr ( n r -- nCr ) 1 swap 0 ?do over i - i 1+ */ loop nip ; 20 value m : onerows ( row -- ) CR DUP 4 .R m 1+ 0 DO dup I nCr dup 0= if drop else 7 .R then LOOP DROP ; : Table ( -- ) CR CR 4 spaces m 1+ 0 DO I 7 .R LOOP ( display column numbers ) m 1+ 1 DO I onerows LOOP ; table