So far we’ve only talked about signed singlelength numbers. In this chapter we’ll introduce unsigned numbers and doublelength numbers, as well as a whole passel of new operators to go along with them.
This chapter is divided in two sections:
For everyone — this section continues our discussion of Forth for beginners and experts alike, and explains how Forth handles signed and unsigned, single and doublelength numbers.
Section 1 — For Beginners
Signed versus Unsigned Numbers
All digital computers store numbers in binary form. In Forth, the we speak of the stack in terms of the implementation’s “cell size” (common sizes are 16, 32, and 64 bits, but other cell sizes are possible). Below is a view of the least significant sixteen bits of a cell, showing the value of each bit:
If every bit were to contain a 1, the total for just these sixteen bits would be 65,535. Thus in 32 bits we can express any value between 0 and 4,294,967,295. Because this kind of number does not let us express negative values, we call it an “unsigned number.” We indicate unsigned numbers with the letter “u” in our tables and stack notations.
But what about negative numbers? In order to be able to express a positive or negative number, we need to sacrifice one bit that will essentially indicate sign. This bit is the one at the far left, the “highorder bit.” In 31 bits we can express a number as high as 2,147,483,647. When the sign bit contains 1, then we can go an equal distance back into the negative numbers. Thus within 32 bits we can represent any number from 2,147,483,648 to +2,147,483,647. This should look familiar to you as the range of a singlelength number, which we denote with the letter “n.”
Before we leave you with any misconceptions, we’d better clarify the way negative numbers are represented. You might think that it’s a simple matter of setting the sign bit to indicate whether a number is positive or negative, but it doesn’t work that way.
To explain how negative numbers are represented, let’s return to decimal notation and examine a counter such as that found on many web pages.
Let’s say the counter has three digits, not five. As more people visit the page, the counter wheels turn and the number increases. Starting once again with the counter at 0, now imagine you badly regret having visited the page and could “unvisit” it by rolling the counter wheels backward. The first number you see is 999, which is, in a sense, the same as 1. The next number will be 998, which is the same as 2, and so on.
The representation of signed numbers in a computer is similar.
Starting with the 32bit number
0000,0000,0000,0000,0000,0000,0000,0000
and going backwards one number, we get
1111,1111,1111,1111,1111,1111,1111,1111 (thirtytwo ones)
which stands for 4,294,967,295 in unsigned notation as well as for 1 in signed notation. The number
1111,1111,1111,1111,1111,1111,1111,1110
which stands for 4,294,967,294 in unsigned notation, represents 2 in signed notation.
Here’s a chart that shows how a binary number on the stack can be used either as an unsigned number or as a signed number:
This bizarreseeming method for representing negative values makes it possible for the computer to use the same procedures for subtraction as for addition.
To show how this works, let’s take a very simple problem:
2
1
Subtracting one from two is the same as adding two plus negative one. In singlelength binary notation, the two looks like this:
0000,0000,0000,0000,0000,0000,0000,0010
while negativeone looks like this:
1111,1111,1111,1111,1111,1111,1111,1111
The computer adds them up the same way we would on paper; that is when the total of any column exceeds one, it carries a one into the next column. The result looks like this:
0000,0000,0000,0000,0000,0000,0000,0010 +1111,1111,1111,1111,1111,1111,1111,1111 10000,0000,0000,0000,0000,0000,0000,0001
As you can see, the computer had to carry a one into every column all the way across, and ended up with a one in the thirtythird place. But since the stack is only thirtytwo bits wide, the result is simply
0000,0000,0000,0000,0000,0000,0000,0001
which is the correct answer, one.
We needn’t explain how the computer converts a positive number to negative, but we will tell you that the process is called “two’s complementing.”
Arithmetic Shift
While we’re on the subject of how a computer performs certain mathematical operations, we’ll explain what is meant by the mysterious phrases back in Chap. 5: “arithmetic left shift” and “arithmetic right shift.”
A Forth Instant Replay  

2* 
( n  n*2 ) 
Multiplies by two (arithmetic left shift)  
2/ 
( n  n/2 ) 
Divides by two (arithmetic right shift)  
LSHIFT 
( n u  n*2^u ) 
Logical left shift over u positions  
RSHIFT 
( n  n/2^u ) 
Logical right shift over u positions 
To illustrate, let’s pick a number, say six, and write it in binary form:
0000,0000,0000,0000,0000,0000,0000,0110
(4+2). Now let’s shift every digit one place to the left, and put a zero in the vacant place in the one’s column.
0000,0000,0000,0000,0000,0000,0000,1100
This is the binary representation of twelve (8+4), which is exactly double the original number. This works in all cases, and it also works in reverse. If you shift every digit one place to the right and fill the vacant digit with a zero, the result will always be half of the original value.
In arithmetic shift, the sign bit does not get shifted. This means that a positive number will stay positive and a negative number will stay negative when you divide or multiply it by two.
When the highorder bit shifts with all the other bits, the term is “logical shift.” In Forth you can do a logical shift of up to 32 places with the words LSHIFT and RSHIFT.
The important thing for you to know is that most computers can shift digits much more quickly than they can go through all the folderol of normal division or multiplication. When speed is critical, it’s much better to say
2*
than
2 *
and it may even be better to say
2* 2* 2*
than
8 *
depending on your particular model of computer, but this topic is getting too technical for right now.
An Introduction to Doublelength Numbers
A doublelength number is just what you probably expected it would be: a number that is represented in two cells instead of one. In a 32bit Forth implementation, signed doublelength numbers have a range of 9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 (signed) or 0 to 18,446,744,073,709,551,615 (unsigned).
In Forth, a doublelength number takes the place of two singlelength numbers on the stack. Operators like 2DUP are useful either for doublelength numbers or for pairs of singlelength numbers.
One more thing we should explain: to the nonForthspeaking computer world, the term “double word” could mean a 32bit value, or four bytes. But in Forth, “word” means a defined command. So in order to avoid confusion, Forth programmers refer to a single number on the stack as a “cell.” A doublelength number requires two cells.
Other Number Bases
As you get more involved in programming, you’ll need to employ other number bases besides decimal and binary, particularly hexadecimal (base 16) and possible octal (base 8). Since we’ll be talking about these two number bases later on in this chapter, we think you might like an introduction now.
Computer people began using hexadecimal and octal numbers for one main reason: computers think in binary and human beings have a hard time reading long binary numbers. For people, it’s much easier to convert binary to hexadecimal than binary to decimal, because sixteen is an even power of two, while ten is not. The same is true with octal. So programmers usually use hex or octal to express the binary numbers that the computer uses for things like addresses and machine codes. Hexadecimal (or simply “hex”) looks strange at first since it uses the letters A through F.
Decimal  Binary  Hexadecimal 

0 
0000 
0 
1 
0001 
1 
2 
0010 
2 
3 
0011 
3 
4 
0100 
4 
5 
0101 
5 
6 
0110 
6 
7 
0111 
7 
8 
1000 
8 
9 
1001 
9 
10 
1010 
A 
11 
1011 
B 
12 
1100 
C 
13 
1101 
D 
14 
1110 
E 
15 
1111 
F 
Let’s take a singlelength binary number:
00000000000000000111101110100001
To convert this number to hexadecimal, we first subdivide it into eight units of four bits each:
 0000  0000  0000  0000  0111  1011  1010  0001 
then convert each 4bit unit to its hex equivalent:
00007BA1
or simply 7BA1.
Octal numbers use only the numerals 0 through 7. Because nowadays most computers use hexadecimal representation, we’ll skip an octal conversion example.
We’ll have more on conversions in the section titled “Number Conversions” later in this chapter.
The ASCII Character Set
If the computer uses binary notation to store numbers, how does it store characters and other symbols? Binary, again, but in a special code that was adopted as an industry standard many years ago. The code is called the American Standard Code for Information Interchange, usually abbreviated ASCII.
Table 71 shows each ASCII character in the system, its ISO 6461983, ISO 7bit coded character set for information interchange, International Reference Version equivalent (IRV), and its hexadecimal form.
The characters in the first column (ASCII codes 01F hex) are called “control characters” because they indicate that the terminal or computer is supposed to do something like ring its bell, backspace, start a new line, etc. The remaining characters are called “printing characters” because they produce visible characters including letters, the numerals zero through nine, all available symbols and even the blank space (hex 20). The only exception is DEL (hex 7F), which is a signal to the computer to ignore the last character sent.
In Chap. 1 we introduced the word EMIT. EMIT takes an ASCII code on the stack and sends it to the terminal so that the terminal will print it as a character. For example,
65 EMIT↵>A ok 66 EMIT↵B ok
etc. (We’re using the decimal, rather than the hex, equivalent because that’s what your computer is most likely expecting right now.)
Why not test EMIT on every printing character, “automatically”?
: PRINTABLES 127 32 DO I EMIT SPACE LOOP ;
PRINTABLES will emit every printable character in the ASCII set; that is, the characters from decimal 32 to decimal 126. (We’re using the ASCII codes as our DO loop index.)
PRINTABLES↵ ! " # $ % & ' ( ) * + ,  . / ...ok
Hex ASCII  Hex ASCII  Hex IRV ASCII  Hex IRV ASCII  Hex IRV ASCII  Hex IRV ASCII  Hex IRV ASCII  Hex IRV ASCII 

00 NUL 
10 DLE 
20 
30 0 0 
40 @ @ 
50 P P 
60 ' ' 
70 p p 
01 SOH 
11 DC1 
21 ! ! 
31 1 1 
41 A A 
51 Q Q 
61 a a 
71 q q 
02 STX 
12 DC2 
22 " " 
32 2 2 
42 B B 
52 R R 
62 b b 
72 r r 
03 ETX 
13 DC3 
23 # # 
33 3 3 
43 C C 
53 S S 
63 c c 
73 s s 
04 EOT 
14 DC4 
24  $ 
34 4 4 
44 D D 
54 T T 
64 d d 
74 t t 
05 ENQ 
15 NAK 
25 % % 
35 5 5 
45 E E 
55 U U 
65 e e 
75 u u 
06 ACK 
16 SYN 
26 & & 
36 6 6 
46 F F 
56 V V 
66 f f 
76 v v 
07 BEL 
17 ETB 
27 ' ' 
37 7 7 
47 G G 
57 W W 
67 g g 
77 w w 
08 BS 
18 CAN 
28 ( ( 
38 8 8 
48 H H 
58 X X 
68 h h 
78 x x 
09 HT 
19 EM 
29 ) ) 
39 9 9 
49 I I 
59 Y Y 
69 i i 
79 y y 
0A LF 
1A SUB 
2A * * 
3A : : 
4A J J 
5A Z Z 
6A j j 
7A z z 
0B VT 
1B ESC 
2B + + 
3B ; ; 
4B K K 
5B [ [ 
6B k k 
7B { { 
0C FF 
1C FS 
2C , , 
3C < < 
4C L L 
5C \ \ 
6C l l 
7C   
0D CR 
1D GS 
2D   
3D = = 
4D M M 
5D ] ] 
6D m m 
7D } } 
0E SM 
1E RS 
2E . . 
3E > > 
4E N N 
5E ^ ^ 
6E n n 
7E ~ ~ 
0F SI 
1F US 
2F / / 
3F ? ? 
4F O O 
5F 
6F o o 

name  operation  decimal equivalent 

BS  backspace  8 
LF  line feed  10 
CR  carriage return  13 
Experiment with these control characters, and see what they do.
ASCII is designed so that each character can be represented by one byte. The tables in this book use the letter "c" to indicate a byte value that is being used as a coded ASCII character.
Bit Logic
The words AND and OR (which we introduced in Chap. 4) use "bit logic"; that is, each bit is treated independently, and there are no "carries" from one bitplace to the next. For example, let's see what happens when we AND these two binary numbers:
0000,0000,0000,0000,0000,0000,1111,1111
0000,0000,0000,0000,0110,0101,1010,0010 AND
0000,0000,0000,0000,0000,0000,1010,0010
For any resultbit to be "1," the respective bits in both arguments must be "1." Notice in this example that the argument on top contains all zeroes in the highorder bytes and all ones in the loworder byte. The effect on the second argument in this example is that the loworder eight bits are kept but the highorder twentyfour bits are all set to zero. Here the first argument is being used as a "mask," to mask out the highorder bytes of the second argument.
The word OR also uses bit logic. For example,
1000,0100,0010,0001,1000,1001,0000,1001
0110,0110,0110,0110,0000,0011,1100,1000 OR
1110,0110,0110,0111,1000,1011,1100,1001
A "1" in either argument produces a "1" in the result. Again, each column is treated separately,with no carries.
By clever use of masks, we could even use a 32bit value to hold 32 separate flags. For example,we could find out whether this bit
1000,0100,0010,0001,1000,1001,0000,1001 ^
is "1" or "0" by masking out all other flags, like this:
1000,0100,0010,0001,1000,1001,0000,1001
0000,0000,0000,0000,1000,0000,0000,0000 AND
0000,0000,0000,0000,1000,0000,0000,0000
Since the bit was "1," the result is "true." Had it been "0," the result would have been "0" or"false."
We could set the flag to "0" without affecting the other flags by using this technique:
1000,0100,0010,0001,1000,1001,0000,1001
1111,1111,1111,1111,0111,1111,1111,1111 AND
1000,0100,0010,0001,0000,1001,0000,1001 ^
We used a mask that contains all "1"s except for the bit we wanted to set to "0." We can set the same flag back to "1" by using this technique:
1000,0100,0010,0001,0000,1001,0000,1001
0000,0000,0000,0000,1000,0000,0000,0000 OR
1000,0100,0010,0001,1000,1001,0000,1001 ^
Section 2 — For Everybody
Signed and Unsigned Numbers
Back in Chap. 1 we introduced the word NUMBER. If the word FIND can't find an incoming string in the dictionary, it hands it over to the word NUMBER. NUMBER then attempts to convert the string into a number expressed in binary form. If NUMBER succeeds, it pushes the binary equivalent onto the stack.
For Beginners
This means that NUMBER does not check whether the number you've entered as a singlelength number exceeds the proper range. If you enter a giant number, NUMBER converts it but only saves the least significant thirtytwo digits.
NUMBER does not do any rangechecking. Because of this, NUMBER can convert either signed or unsigned numbers.
For instance, if you enter any number between 2147483648 and 4294967295, NUMBER will convert it as an unsigned number. Any value between 2147483648 and 1 will be stored as a two'scomplement integer.
This is an important point: the stack can be used to hold either signed or unsigned numbers. Whether a binary value is interpreted as signed or unsigned depends on the operators that you apply to it. You decide which form is better for a given situation, then stick to your choice.
We've introduced the word ., which prints a value on the stack as a signed number:
4294967295 .↵1 ok
The word U. prints the binary representation as an unsigned number:
4294967295 U.↵4294967295 ok
U. 
( u  ) 
Prints the unsigned singlelength number, followed by a space. 
In this book the letter "n" signifies signed singlelength numbers, while the letter "u" signifies unsigned singlelength numbers. (We've already introduced U.R, which prints an unsigned singlelength number rightjustified within a given column width.)
Here is a table of additional words that use unsigned numbers:  

UM* 
( u1 u2  ud ) 
Multiplies two singlelength numbers. Returns a doublelength result. All values are unsigned.  
UM/MOD 
( ud u1  u2 u3 ) 
Divides a doublelength by a singlelength number. Returns a singlelength quotient u2 and remainder u3. All values are unsigned.  
U< 
( u1 u2  f ) 
Leaves true if u1 < u2, where both are treated as singlelength unsigned integers. 
Number Bases
When you first start Forth, all number conversions use base ten (decimal), for both input and output.
You can easily change the base by executing one of the following commands:  

HEX 
(  ) 
Sets the base to sixteen.  
OCTAL 
(  ) 
Sets the base to eight (available on some systems).  
DECIMAL 
(  ) 
Returns the base to ten. 
When you change the number base, its stays changed until you change it again. So be sure to declare DECIMAL as soon as you're done with another number base.
These commands make it easy to do number conversions in "calculator style."
For example, to convert decimal 100 into hexadecimal, enter
DECIMAL 100 HEX .↵64 ok
To convert hex F into decimal (remember you are already in hex), enter
0F DECIMAL .↵15 ok
Make it a habit, starting right now, to precede each hexadecimal value with a zero, as in
0A 0B 0F
This practice avoids mixups with possibly predefined words as DEADBEEF, BAD, DEC etc.
Handy Hint
A definition of BINARY — or AnyARY
Beginners who want to see what numbers look like in binary notation may enter this definition:
: BINARY 2 BASE ! ;
The new word BINARY will operate just like OCTAL or HEX but will change the number base to two. On systems which do not have the word OCTAL, experimenters may define
: OCTAL 8 BASE ! ;
Doublelength Numbers
Most ANS Forth systems support doublelength numbers to some degree. The standard way to enter a doublelength number onto the stack (whether from the keyboard or from a file) is to punctuate it with a period at the end. When the text interpreter processes a number that is immediately followed by a decimal point and is not found as a definition name, it is converted to a doublecell number.
For example, when you type
200000.↵
NUMBER recognizes the period at the as a signal that this value should be converted to doublelength. NUMBER then pushes the value onto the stack as two consecutive "cells" (cell is the Forth term for a singlelength item on the stack), the high order cell on top.
Some Forth implementations (including SwiftForth) will convert any number that contains the following characters as a double number:
+ ,  . / :
The Forth word D. prints a doublelength number without any punctuation.  

D. 
( d  ) 
Prints the signed doublelength number, followed by one space. 
In this book, the letter "d" stands for a doublelength signed integer.
For example, having entered a doublelength number, if you were now to execute D.,the computer would respond:
D.↵200000 ok
In the next section we'll show you how to define your own equivalents to D. which will print whatever punctuation you want along with the number.
Number Formatting — Doublelength Unsigned
$200.00 12/31/80 9996784 6:32:59 98.6
The above numbers represent the kinds of output you can create by defining your own "numberformatting words" in Forth. This section will show you how.
The simplest numberformatting definition we could write would be
: UD. <# #S #> TYPE ;
UD. will print an unsigned doublelength number. The words <# and #> (respectively pronounced bracketnumber and numberbracket) signify the beginning and the end of the numberconversion process. In this definition, the entire conversion is being performed by the single word #S (pronounced numbers). #S converts the value on the stack into ASCII characters. It will only produce as many digits as are necessary to represent the number; it will not produce leading zeroes. But it always produces at least one digit, which will be zero if the value was zero. For example:
12,345 UD.↵12345ok 12. UD.↵12ok 0. UD.↵0ok
The word TYPE prints the characters that represent the number at your terminal. Notice that there is no space between the number and the "ok." To get a space,you would simply add the word SPACE, like this:
: UD. <# #S #> TYPE SPACE ;
Now let's say we have a phone number on the stack, expressed as a doublelength unsigned integer. For example, we may have typed in:
9996784
(remember that the hyphen tells NUMBER to treat this as a doublelength value). We want to define a word that will format this value back as a phone number. Let's call it .PH# (for "print the phone number") and define it thus:
: .PH# <# # # # # [CHAR]  HOLD #S #> TYPE SPACE ;
Our definition of .PH# has everything that UD. has, and more. The Forth word # (pronounced number) produces a single digit only. A numberformatting definition is reversed from the order in which the number will be printed, so the phrase
# # # #
produces the rightmost four digits of the phone number.
Now it's time to insert the hyphen. Using [CHAR] we can get the code value of this ASCII character on the stack. The Forth word HOLD takes this ASCII code and inserts it into the formatted number character string.
We now have three digits left. We might use the phrase
# # #
but it is easier to simply use the word #S, which will automatically convert the rest of the number for us.
If you are more familiar with ASCII codes represented in hexadecimal form, you can use this definition instead:
HEX : .PH# <# # # # # 02D HOLD #S #> TYPE SPACE ; DECIMAL
Either way, the compiled definition will be exactly the same.
Now let's format an unsigned doublelength number as a date, in the following form:
6/15/03
Here is the definition:
: .DATE <# # # [CHAR] / HOLD # # [CHAR] / HOLD #S #> TYPE SPACE ;
Let's follow the above definition, remembering that it is written in reverse order from the output. The phrase
# # [CHAR] / HOLD
produces the rightmost two digits (representing the year) and the rightmost slash. The next occurrence of the same phrase produces the middle two digits (representing the day) and the leftmost slash. Finally #S produces the leftmost two digits(representing the month).
We could have just as easily defined
# # [CHAR] / HOLD
as its own word and used this word twice in the definition of .DATE.
Since you have control over the conversion process, you can actually convert different digits in different number bases, a feature which is useful in formatting such numbers as hours and minutes. For example, let's say that you have the time in seconds on the stack, and you want a word which will print hh:mm:ss. You might define it this way:
: SEXTAL 6 BASE ! ; : :00 # SEXTAL # DECIMAL [CHAR] : HOLD ; : SEC <# :00 :00 #S #> TYPE SPACE ;
We will use the word :00 to format the seconds and minutes. Both seconds and minutes are modulo60, so the right digit can go as high as nine, but the left digit can only go up to five. Thus in the definition of :00 we convert the first digit (the one on the right) as a decimal number, then go into "sextal" (base 6) and convert the left digit. Finally, we return to decimal and insert the colon character. After :00 converts the seconds and the minutes,#S converts the remaining hours.
For example, if we had 4500 seconds on the stack, we would get
4500. SEC↵1:15:00 ok
Table 72 summarizes the Forth words that are used in number formatting. (Note the "KEY" at the bottom, which serves as a reminder of the meanings of "n," "d," etc.)
Table 72 — Number Formatting  

<# 
Begins the number conversion process. Expects the unsigned doublelength number on the stack. 
# 
Converts one digit and puts it into an output character string. # always produces a digit — if you're out of significant digits, you'll still get a zero for every #. 
#S 
Converts the number until the result is zero. Always produces at least one digit (0 if the value is zero). 
c HOLD 
Inserts, at the current position in the character string being formatted, a character c whose ASCII value is on the stack. HOLD (or a word which uses HOLD) must be used between <# and #>. 
SIGN 
Inserts a minus sign in the output string if the top of stack is negative. Usually used with ROT immediately before #> for a leading minus sign. 
#> 
Completes number conversion by leaving the character count and address on the stack (these are the appropriate arguments for TYPE). 
phrase  stack 

<# ... #> 
( ud  addr u ) 
doublelength unsigned  
<# ... ROT SIGN #> 
( n d  addr u ) 
doublelength signed (where n is the highorder cell of d and d is the absolute value of d). 
n, n1, ...
= singlelength signed
d, d1, ...
= doublelength signed
u, u1, ...
= singlelength unsigned
addr
= address
c
= ASCII character value
Number Formatting — Signed and Singlelength
So far we have formatted only unsigned doublelength numbers. The <#...#> form expects only unsigned doublelength numbers, but we can use it for other types of numbers by making certain arrangements on the stack.
For instance, let's look at a simplified version of the system definition of D. (which prints a signed doublelength number):
: D. TUCK DABS <# #S ROT SIGN #> TYPE SPACE ;
The phrase ROT SIGN inserts a minus string in the character string if the third number on the stack is negative. We have prepared for this test by putting a copy of the highorder cell (the one with the sign bit) at the bottom of the stack, by using the word TUCK.
Because <# expects only unsigned doublelength numbers,we must take the absolute value of our doublelength signed number, with the word DABS. We now have the proper arrangement of arguments on the stack for the <#...#> phrase. In some cases, such as accounting, we may want a negative number to be written
12345
in which case we would place the phrase ROT SIGN at the left side of our <#...#> phrase, like this:
<# ROT SIGN #S #>
Let's define a word which will print a signed doublelength number with a decimal point and two decimal places to the right of the decimal. Since this is the form most often used for writing dollars and cents, let's call it
.$
and define it like this:
: .$ TUCK DABS <# # # [CHAR] . HOLD #S ROT SIGN [CHAR] $ HOLD #> TYPE SPACE ;
Let's try it:
2000.00 .$↵$2000.00 ok
or even
2,000.00 .$↵$2000.00 ok
We recommend that you save .$, since we'll be using it in some future examples.
You can also write special formats for singlelength numbers. For example, if you want to use an unsigned singlelength number, simply put a zero on the stack before the word <#. This effectively changes the singlelength number into a doublelength number which is so small that it has nothing (zero) in the highorder cell. To format a signed singlelength number, again you must supply a zero as a highorder cell. But you must also leave a copy of the signed number in the third stack position for ROT SIGN, and you must leave the absolute value of the number in the second stack position. The phrase to do all this is
DUP ABS 0
Number to be printed  Precede <# by 

doublelength, unsigned  (nothing needed) 
63bit, plus sign  TUCK DABS (to save the sign in the third stack position for ROT SIGN ) 
singlelength, unsigned  0 (to give a dummy highorder part) 
31bit, plus sign  DUP ABS 0 (to save the sign) 
Doublelength Operators
Here is a list of doublelength math operators:  

D.R 
( d width  ) 
Prints the signed doublelength number, rightjustified within the field width.  
D+ 
( d1 d2  dsum ) 
Adds two doublelength numbers.  
D 
( d1 d2  ddiff) 
Subtracts two doublelength numbers (d1d2).  
DNEGATE 
( d  d) 
Changes the sign of a doublelength number.  
DMAX 
( d1 d2  dmax ) 
Returns the maximum of two doublelength numbers (d1d2).  
DMIN 
( d1 d2  dmin ) 
Returns the minimum of two doublelength numbers (d1d2).  
D= 
( d1 d2  f ) 
Returns true if d1 and d2 are equal.  
D0= 
( d  f ) 
Returns true if d is zero.  
D< 
( d1 d2  f ) 
Returns true if d1 is less than d2.  
DU< 
( ud1 ud2  f ) 
Returns true if ud1 is less than ud2. Both numbers are unsigned. 
The initial "D" signifies that these operators may only be used for doublelength operations, whereas the initial "2," as in 2SWAP and 2DUP, signifies that these operators may be used either for doublelength numbers or for pairs of numbers.
Here's an example using D+:
200,000 300,000 D+ D.↵500000 ok
Mixedlength Operators
Here's a table of very useful Forth words which operate on a combination of single and doublelength numbers:  

M+ 
( d n  dsum ) 
Adds a doublelength number to a singlelength number. Returns a doublelength result.  
SM/REM 
( d n1  n2 n3 ) 
Divide d1 by n1, giving the symmetric quotient n3 and the remainder n2. Input and output stack arguments are signed. An ambiguous condition exists if n1 is zero or if the quotient lies outside the range of a singlecell signed integer.  
FM/MOD 
( d n1  n2 n3 ) 
Divide d1 by n1, giving the floored quotient n3 and the remainder n2. Input and output stack arguments are signed. An ambiguous condition exists if n1 is zero or if the quotient lies outside the range of a singlecell signed integer.  
M* 
( n1 n2  dprod ) 
Multiplies two singlelength numbers. Returns a doublelength result. All values are signed.  
M*/ 
( d +n1 n2  dresult ) 
Multiplies a doublelength number by a singlelength number and divides the triplelength result by a singlelength number (d*n/n). Returns a doublelength result. All values are signed. 
Here's an example using M+:
200,000 7 M+ D.↵200007 ok
Or, using M*/, we can redefine our earlier version of % so that it will accept a doublelength argument:
: % 100 M*/ ;
as in
200.50 15 % D.↵3007 ok
If you have loaded the definition of .$ we gave in the last Handy Hint, you can enter
200.50 15 % .$↵$30.07 ok
We can redefine our earlier definition of R% to get a rounded doublelength result, like this:
: R% 10 M*/ 5 M+ 10 SM/REM NIP ;
then
987.65 15 R% .$↵$30.08 ok
Notice that M*/ is the only readymade Forth word which performs multiplication on a doublelength argument. To multiply 200,000 by 3, for instance, we must supply a "1" as a dummy denominator:
200,000 3 1 M*/ D.↵600000 ok
since
3
1
is the same as 3.
M*/ is also the only readymade Forth word that performs division with a doublelength result. So to divide 200,000 by 4, for instance, we must supply a "1" asa dummy numerator:
200,000 1 4 M*/ D.↵50000 ok
Numbers in Definitions
When a definition contains a number, such as
: SCOREMORE 20 + ;
the number is compiled into the dictionary in binary form, just as it looks on the stack.
The number's binary value depends on the number base at the time you compile the definition. For example, if you were to enter
HEX : SCOREMORE 14 + ; DECIMAL
the dictionary definition would contain the hex value 14, which is the same as the decimal value 20 (16+4). Henceforth, SCOREMORE will always add the equivalent of the decimal 20 to the value on the stack, regardless of the current number base.
If, on the other hand, you were to put the word HEX inside the definition, then you would change the number base when you execute the definition.
For example, if you were to define:
DECIMAL : EXAMPLE HEX 20 . DECIMAL ;
the number would be compiled as the binary equivalent of decimal 20, since DECIMAL was current at compilation time.
At execution time, here's what happens:
EXAMPLE↵14 ok
The number is output in hexadecimal.
For the record, a number that appears inside a definition is called a "literal." (Unlike the words in the rest of the definition which allude to other definitions, a number must be taken literally.)
Chapter Summary
Forth Words
Here is a list of the Forth words we've covered in this chapter: Unsigned Operators 


U. 
( u  ) 
Prints the unsigned singlelength number, followed by one space.  
UM* 
( u1 u2  ud ) 
Multiplies two singlelength numbers. Returns a doublelength result. All values are unsigned.  
UM/MOD 
( ud u1  u2 u3 ) 
Divides a doublelength by a singlelength number. Returns a singlelength quotient and remainder. All values are unsigned.  
U< 
( u1 u2  f ) 
Leaves true if u1 < u2, where both are treated as singlelength unsigned integers. 
Number Bases  

HEX 
(  ) 
Sets the base to sixteen.  
OCTAL 
(  ) 
Sets the base to eight (available on some systems).  
DECIMAL 
(  ) 
Returns the base to ten. 
Number Formatting Operators  

<# 
Begins the number conversion process. Expects the unsigned doublelength number on the stack. 
# 
Converts one digit and puts it into an output character string. # always produces a digit — if you're out of significant digits, you'll still get a zero for every #. 
#S 
Converts the number until the result is zero. Always produces at least one digit (0 if the value is zero). 
c HOLD 
Inserts, at the current position in the character string being formatted, a character c whose ASCII value is on the stack. HOLD (or a word which uses HOLD) must be used between <# and #>. 
SIGN 
Inserts a minus sign in the output string if the top of stack is negative. Usually used with ROT immediately before #> for a leading minus sign. 
#> 
Completes number conversion by leaving the character count and address on the stack (these are the appropriate arguments for TYPE). 
phrase  stack 

<# ... #> 
( d  addr u ) 
doublelength unsigned  
<# ... ROT SIGN #> 
( n d  addr u ) 
doublelength signed (where n is the highorder cell of d and d is the absolute value of d). 
Doublelength operators  

D+ 
( d1 d2  dsum ) 
Adds two doublelength numbers.  
D 
( d1 d2  ddiff ) 
Subtracts two doublelength numbers (d1d2).  
DNEGATE 
( d  d ) 
Changes the sign of a doublelength number.  
DMAX 
( d1 d2  dmax ) 
Returns the maximum of two doublelength numbers (d1d2).  
DMIN 
( d1 d2  dmin ) 
Returns the minimum of two doublelength numbers (d1d2).  
D= 
( d1 d2  f ) 
Returns true if d1 and d2 are equal.  
D0= 
( d  f ) 
Returns true if d is zero.  
D< 
( d1 d2  f ) 
Returns true if d1 is less than d2.  
DU< 
( ud1 ud2  f ) 
Returns true if ud1 is less than ud2. Both numbers are unsigned.  
D.R 
( d width  ) 
Prints the signed doublelength number, rightjustified within the field width. 
Mixedlength operators  

M+ 
( d n  dsum ) 
Adds a doublelength number to a singlelength number. Returns a doublelength result.  
SM/REM 
( d n1  n2 n3 ) 
Divide d1 by n1, giving the symmetric quotient n3 and the remainder n2. Input and output stack arguments are signed. An ambiguous condition exists if n1 is zero or if the quotient lies outside the range of a singlecell signed integer.  
FM/MOD 
( d n1  n2 n3 ) 
Divide d1 by n1, giving the floored quotient n3 and the remainder n2. Input and output stack arguments are signed. An ambiguous condition exists if n1 is zero or if the quotient lies outside the range of a singlecell signed integer.  
M* 
( n1 n2  dprod ) 
Multiplies two singlelength numbers. Returns a doublelength result. All values are signed.  
M*/ 
( d +n1 n2  dresult ) 
Multiplies a doublelength number by a singlelength number and divides the triplelength result by a singlelength number (d*n/n). Returns a doublelength result. All values are signed. 
n, n1, ...
= singlelength signed
d, d1, ...
= doublelength signed
u, u1, ...
= singlelength unsigned
addr
= address
c
= ASCII character value
Review of Terms
 Arithmetic left and right shift
 the process of shifting all bits in a number, except the sign bit, to the left or right, in effect doubling or halving the (assumed signed) number, respectively.
 Logical left and right shift
 the process of shifting all bits in a number, including the sign bit, to the left or right, in effect doubling or halving the (assumed unsigned) number, respectively.
 ASCII
 a standardized system of representing input/output characters as byte values. Acronym for American Standard Code for Information Interchange. (Pronounced askkey)
 Binary
 number base 2.
 Byte
 the standard term for an 8bit value.
 Cell
 the Forth term for a singlecell value.
 Decimal
 number base 10.
 Hexadecimal
 number base 16.
 Literal
 in general, a number of symbol which represents only itself; in Forth, a number that appears inside a definition.
 Mask
 a value which can be " superimposed" over another, hiding certain bits and revealing only those bits that we are interested in.
 Number formatting
 the process of printing a number, usually in a special form such as 3/13/03 or $47.93.
 Octal
 number base 8.
 Sign bit highorder bit
 the bit which, for a signed number, indicates whether it is positive or negative and, for an unsigned number, represents the bit of the highest magnitude.
 Two's complement
 for any number, the number of equal absolute value but opposite sign. To calculate 10  4, the computer first produces the two's complement of 4, (i.e., 4), then computes 10 + (4).
 Unsigned number
 a number which is assumed to be positive.
 Unsigned singlelength number
 an integer which falls within the range of 0 to 2147483647.
 Word
 In Forth, a defined dictionary entry, elsewhere, a term for a 16bit value.
 Integer division
 produces a quotient q and a remainder r by dividing operand a by operand b. Division operations return q, r, or both. The identity b*q + r = a holds for all a and b.
 Floored division
 is integer division in which the remainder carries the sign of the divisor or is zero, and the quotient is rounded to its arithmetic floor.
 Symmetric division
 is integer division in which the remainder carries the sign of the dividend or is zero and the quotient is the mathematical quotient "rounded towards zero" or "truncated".
Problems — Chapter 7
 Veronica Wainwright couldn't remember the upper limit for a signed singlelength number, and she had no book to refer to, only a Forth terminal. So she wrote a definition called NMAX, using a BEGIN... UNTIL loop. When she executed it, she got
↵2147483647 ok
What was her definition? [ answer ]
 Since you now know that AND and OR employ bit logic, explain why the following example must use OR instead of +:
: MATCH humorous sensitive AND artloving musicloving OR AND smoking 0= AND IF ." I have someone you should meet " THEN ;
 Write a definition that "rings" your terminal's bell three times. Make sure that there is enough of a delay between the bells so that they are distinguishable. Each time the bell rings, the word "BEEP" should appear on the terminal screen. [ answer ]
 Rewrite the temperature conversion definitions which you created for the problems in Chap. 5. This time assume that the input and resulting temperatures are to be doublelength signed integers which are scaled (i.e., multiplied) by ten. For example, if 10.5 degrees is entered, it is a 32bit integer with a value of 105. [ answer ]
 Write a formatted output word named .DEG which will display a doublelength signed integer scaled by ten as a string of digits, a decimal point, and one fractional digit. For example:
12.3 .DEG↵12.3 ok
[ answer ]
 Solve the following conversions:
0.0° F in Centigrade
212.0° F in Centigrade
20.0° F in Centigrade
16.0° C in Fahrenheit
40.0° C in Fahrenheit
100.0° K in Centigrade
100.0° K in Fahrenheit
233.0° K in Centigrade
233.0° K in Fahrenheit  Write a routine which evaluates the quadratic equation 7x^{2} + 20x + 5 given x, and returns a doublelength result.
 How large an x will work without overflowing sixtyfour bits as a signed number?
 Write a word which prints the numbers 0 through 16 (decimal) in decimal, hexadecimal, and binary form in three columns. E.g.,
DECIMAL 0 HEX 0 BINARY 0 DECIMAL 1 HEX 1 BINARY 1 DECIMAL 2 HEX 2 BINARY 10 ... DECIMAL 16 HEX 10 BINARY 10000
[ answer ]
 If you enter
..↵
(two periods not separated by a space) and the system responds "ok," what does this tell you? [ answer ]
 Write a definition for a phonenumber formatting word that will also print the area code with a slash if and only if the number includes an area code. E.g.,
5551234 .PH# 5551234↵ok 310/9996784 .PH#↵310/9996784 ok
[ answer ]