📄 lessons.txt
字号:
: MULTIPLY ( -- )
CR CR 6 SPACES
1 11
FOR DUP 4 .R 1 +
NEXT DROP
1 11
FOR DUP ONEROW 1 +
NEXT DROP
;
( Type MULTIPLY to print the multiplication table )
( Example 11. Calendars )
( Print weekly calendars for any month in any year. )
DECIMAL
VARIABLE JULIAN ( 0 is 1/1/1950, good until 2050 )
VARIABLE LEAP ( 1 for a leap year, 0 otherwise. )
( 1461 CONSTANT 4YEARS ( number of days in 4 years )
: YEAR ( YEAR --, compute Julian date and leap year )
DUP
1949 - 1461 4 */MOD ( days since 1/1/1949 )
365 - JULIAN ! ( 0 for 1/1/1950 )
3 = ( modulus 3 for a leap year )
IF 1 ELSE 0 THEN ( leap year )
LEAP !
DUP 2000 = ( 2000 is not a leap year )
IF 0 LEAP ! THEN
2001 < ( correction due to 2000 )
IF ELSE -1 JULIAN +! THEN
;
: FIRST ( MONTH -- 1ST, 1st of a month from Jan. 1 )
DUP 1 =
IF DROP 0 EXIT THEN ( 0 for Jan. 1 )
DUP 2 =
IF DROP 31 EXIT THEN ( 31 for Feb. 1 )
DUP 3 =
IF DROP 59 LEAP @ + EXIT THEN ( 59/60 for Mar. 1 )
4 - 30624 1000 */
90 + LEAP @ + ( Apr. 1 to Dec. 1 )
;
: STARS 60 FOR 42 EMIT NEXT ; ( form the boarder )
: HEADER ( -- ) ( print title bar )
CR STARS CR
." SUN MON TUE WED THU FRI SAT"
CR STARS CR ( print weekdays )
;
: BLANKS ( MONTH -- ) ( skip days not in this month )
FIRST JULIAN @ + ( Julian date of 1st of month )
7 MOD 8 * SPACES ; ( skip colums if not Sunday )
: DAYS ( MONTH -- ) ( print days in a month )
DUP FIRST ( days of 1st this month )
SWAP 1 + FIRST ( days of 1st next month )
OVER - 1 - ( loop to print the days )
1 SWAP ( first day count -- )
FOR 2DUP + 1 -
JULIAN @ + 7 MOD ( which day in the week? )
IF ELSE CR THEN ( start a new line if Sunday )
DUP 8 U.R ( print day in 8 column field )
1 +
NEXT
2DROP ; ( discard 1st day in this month )
: MONTH ( N -- ) ( print a month calendar )
HEADER DUP BLANKS ( print header )
DAYS CR STARS CR ; ( print days )
: JANUARY YEAR 1 MONTH ;
: FEBRUARY YEAR 2 MONTH ;
: MARCH YEAR 3 MONTH ;
: APRIL YEAR 4 MONTH ;
: MAY YEAR 5 MONTH ;
: JUNE YEAR 6 MONTH ;
: JULY YEAR 7 MONTH ;
: AUGUST YEAR 8 MONTH ;
: SEPTEMBER YEAR 9 MONTH ;
: OCTOBER YEAR 10 MONTH ;
: NOVEMBER YEAR 11 MONTH ;
: DECEMBER YEAR 12 MONTH ;
( To print the calender of April 1999, type:
1999 APRIL
)
( Example 12. Sines and Cosines
Sines and cosines of angles are among the most often encountered
transdential functions, useful in drawing circles and many other
different applications. They are usually computed using floating
numbers for accuracy and dynamic range. However, for graphics
applications in digital systems, single integers in the range from
-32768 to 32767 are sufficient for most purposes. We shall
study the computation of sines and cosines using the single
integers.
The value of sine or cosine of an angle lies between -1.0 and +1.0.
We choose to use the integer 10000 in decimal to represent 1.0
in the computation so that the sines and cosines can be represented
with enough precision for most applications. Pi is therefore
31416, and 90 degree angle is represented by 15708. Angles
are first reduced in to the range from -90 to +90 degrees,
and then converted to radians in the ranges from -15708 to
+15708. From the radians we compute the values of sine and
cosine.
The sines and cosines thus computed are accurate to 1 part in
10000. This algorithm was first published by John Bumgarner
in Forth Dimensions, Volume IV, No. 1, p. 7.
31415 CONSTANT PI
10000 CONSTANT 10K )
VARIABLE XS ( square of scaled angle )
: KN ( n1 n2 -- n3, n3=10000-n1*x*x/n2 where x is the angle )
XS @ SWAP / ( x*x/n2 )
NEGATE 10000 */ ( -n1*x*x/n2 )
10000 + ( 10000-n1*x*x/n2 )
;
: (SIN) ( x -- sine*10K, x in radian*10K )
DUP DUP 10000 */ ( x*x scaled by 10K )
XS ! ( save it in XS )
10000 72 KN ( last term )
42 KN 20 KN 6 KN ( terms 3, 2, and 1 )
10000 */ ( times x )
;
: (COS) ( x -- cosine*10K, x in radian*10K )
DUP 10000 */ XS ! ( compute and save x*x )
10000 56 KN 30 KN 12 KN 2 KN ( serial expansion )
;
: SIN ( degree -- sine*10K )
31415 180 */ ( convert to radian )
(SIN) ( compute sine )
;
: COS ( degree -- cosine*10K )
31415 180 */
(COS)
;
( To test the routines, type:
90 SIN . 9999
45 SIN . 7070
30 SIN . 5000
0 SIN . 0
90 COS . 0
45 COS . 7071
0 COS . 10000 )
( Example 13. Square Root
There are many ways to take the square root of an integer. The
special routine here was first discovered by Wil Baden. Wil
used this routine as a programming challenge while attending
a FORML Conference in Taiwan, 1984.
This algorithm is based on the fact that the square of n+1 is equal
to the sum of the square of n plus 2n+1. You start with an 0 on
the stack and add to it 1, 3, 5, 7, etc., until the sum is greater
than the integer you wished to take the root. That number when
you stopped is the square root.
)
: SQRT ( n -- root )
65025 OVER U< ( largest square it can handle)
IF DROP 255 EXIT THEN ( safety exit )
>R ( save sqaure )
1 1 ( initial square and root )
BEGIN ( set n1 as the limit )
OVER R@ U< ( next square )
WHILE
DUP CELLS 1 + ( n*n+2n+1 )
ROT + SWAP
1 + ( n+1 )
REPEAT
SWAP DROP
R> DROP
;
( Example 14. Radix for Number Conversions )
DECIMAL
( : DECIMAL 10 BASE ! ; )
( : HEX 16 BASE ! ; )
: OCTAL 8 BASE ! ;
: BINARY 2 BASE ! ;
( Try converting numbers among different radices:
DECIMAL 12345 HEX U.
HEX ABCD DECIMAL U.
DECIMAL 100 BINARY U.
BINARY 101010101010 DECIMAL U.
Real programmers impress on novices by carrying a HP calculator
which can convert numbers between decimal and hexadecimal. A
Forth computer has this calculator built in, besides other functions.
)
( Example 15. ASCII Character Table )
: CHARACTER ( n -- )
DUP EMIT HEX DUP 3 .R
OCTAL DUP 4 .R
DECIMAL 3 .R
2 SPACES
;
: LINE ( n -- )
CR
5 FOR DUP CHARACTER
16 +
NEXT
DROP ;
: TABLE ( -- )
32
15 FOR DUP LINE
1 +
NEXT
DROP ;
( Example 16. Random Numbers
Random numbers are often used in computer simulations and computer
games. This random number generator was published in Leo Brodie's
'Starting Forth'.
)
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 )
( To test the routine, type
100 CHOOSE .
100 CHOOSE .
100 CHOOSE .
and varify that the results are randomly distributed betweem 0 and
99 . )
( Example 17. Guess a Number )
: GetNumber ( -- n )
BEGIN
CR ." Enter a Number: " ( show message )
QUERY BL WORD NUMBER? ( get a string )
UNTIL ( repeat until a valid number )
;
( With this utility instruction, we can write a game 'Guess a Number.' )
: InitialNumber ( -- n , set up a number for the player to guess )
CR CR CR ." What limit do you want?"
GetNumber ( ask the user to enter a number )
CR ." I have a number between 0 and " DUP .
CR ." Now you try to guess what it is."
CR
CHOOSE ( choose a random number )
; ( between 0 and limit )
: Check ( n1 -- , allow player to guess, exit when the guess is correct )
BEGIN CR ." Please enter your guess."
GetNumber
2DUP = ( equal? )
IF 2DROP ( discard both numbers )
CR ." Correct!!!"
EXIT
THEN
OVER <
IF CR ." Too low."
ELSE CR ." Too high!"
THEN CR
0 UNTIL ( always repeat )
;
: Greet ( -- )
CR CR CR ." GUESS A NUMBER"
CR ." This is a number guessing game. I'll think"
CR ." of a number between 0 and any limit you want."
CR ." (It should be smaller than 32000.)"
CR ." Then you have to guess what it is."
;
: GUESS ( -- , the game )
Greet
BEGIN InitialNumber ( set initial number)
Check ( let player guess )
CR CR ." Do you want to play again? (Y/N) "
KEY ( get one key )
32 OR 110 = ( exit if it is N or n )
UNTIL
CR CR ." Thank you. Have a good day." ( sign off )
CR
;
( Type 'GUESS' will initialize the game and the computer will entertain
a user for a while. Note the use of the indefinite loop structure:
BEGIN <repeat-clause> [ f ] UNTIL
You can jump out of the infinite loop by the instruction EXIT, which
skips all the instructions in a Forth definition up to ';', which
terminates this definition and continues to the next definition. )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -