Lesson 14
Contents
FixedPoint Arithmetic
The version of Mops that you've been using in this tutorial utilizes fixedpoint arithmetic (also called integer arithmetic) instead of floatingpoint arithmetic. The primary difference between the two is that fixedpoint arithmetic functions only with integers. You had a hint of that when you started experimenting with division in Lesson 3: the answer on the stack was either an integer quotient or a quotientplusremainder (both of which were integers). Floating point arithmetic, on the other hand, allows you to enter numbers with digits to the right of the decimal.
Floatingpoint arithmetic is convenient in many instances, especially when results of operations traditionally are other than whole numbers: financial calculations, for example, which have cents to the right of the decimal point. But floatingpoint also has some drawbacks, which should be particularly important to you as a Mops programmer.
One drawback is that floatingpoint arithmetic takes up more memory in the computer, increasing the size of the Mops kernel. This is not as significant now as it was a even few years ago, when memory was much more expensive.
Second, floatingpoint arithmetic usually takes more time to calculate than fixedpoint. Depending on the computer and the language, a floatingpoint calculation can take up to ten (or in some cases, even a hundred) times as long as the same calculation performed with fixedpoint arithmetic.
And third, floatingpoint arithmetic can be less accurate than fixedpoint in some calculations. You cannot, for example, multiply a number by precisely by the fraction onethird in floatingpoint arithmetic; you must multiply by 0.33333... . And there will always be some error in the calculation, which can compound itself after a couple of further calculations based on this approximation of onethird.
Actually, most programs have no need for floatingpoint arithmetic at all. For this reason, the basic Mops system has only the smaller and faster fixedpoint support, with floatingpoint available as an option for those who need it.
But fixedpoint arithmetic presents a problem of its own, because you may be accustomed to dealing with numbers other than integers, numbers like π (pi) or percentages. To accommodate such numbers, Mops requires that you use scalars, or operations that appear to convert floatingpoint numbers into fixedpoint numbers.
Two of the most used scalars are those that are actually specialcase combinations of familiar arithmetic operations:
*/

( n1 n2 n3  result )

Multiplies ‘n1 ’ times ‘n2 ’ and then divides that result by ‘n3 ’, leaving the final result on the stack.


*/MOD

( n1 n2 n3  remainder result )

Same as */ but leaves both the result and the remainder on the stack.

Notice carefully the order of the items on the stack and how they are treated by the arithmetic operations, because they are not as you would expect in a regular combination of Mops arithmetic operations. But the order allows you to better visualize the process by changing the algebraic infix notation of a problem to Mops' postfix notation. For example, to multiply 100 times the fraction twothirds, the paperandpencil equation
100 * 2 / 3
then becomes
100 2 3 */
Similar operations can be used to work with percentages. Simply put a 100 in place of the ‘n3
’ in the description above and the percentage figure in place of ‘n2
’.
Decimal, Hex, and Binary Arithmetic
When Mops works with numbers "under the hood", it often uses numbering systems other than the traditional decimal (base10) system. The two most often used nondecimal numbering systems are the hexadecimal and binary numbering systems. Each has very different characteristics.
The hexadecimal numbering system is a base16 system. That is, instead of numbers increasing say, from one to two digits after the "ones" digit has cycled from zero through nine, it cycles after fifteen digits. To denote the digits after 9, hexadecimal notation uses the first several letters of the alphabet. Corresponding to decimal 10 is hexadecimal A; decimal 11 is hexadecimal B; and so on through hexadecimal F. A hexadecimal (sometimes shorted to "hex") number is usually preceded by a special sign ($) so you know that $24 is hexadecimal 24 (decimal 36) instead of the decimal 24.
The binary numbering system, at the other extreme, has only two digits, a zero and a one. This system may not seem very useful in light of decimal and hexadecimal systems, but as you get further into the programming with the Mac, You'll find times when binary math is absolutely essential for ease of designing elements such as cursors, text fonts, and icons.
To show you the differences among the three bases, here is a table of the first twenty numbers in each base:
Decimal  Hexadecimal  Binary 

0  0  0000 0000 
1  1  0000 0001 
2  2  0000 0010 
3  3  0000 0011 
4  4  0000 0100 
5  5  0000 0101 
6  6  0000 0110 
7  7  0000 0111 
8  8  0000 1000 
9  9  0000 1001 
10  A  0000 1010 
11  B  0000 1011 
12  C  0000 1100 
13  D  0000 1101 
14  E  0000 1110 
15  F  0000 1111 
16  10  0001 0000 
17  11  0001 0001 
18  12  0001 0010 
19  13  0001 0011 
20  14  0001 0100 
You might have noticed in this list that there is a special relationship between binary and hexadecimal; each time one place of the hexadecimal number reaches the maximum (F), four consecutive places of a binary number reach their maximum (1111). This relationship will prove more important later on.
Although the binary numbers shown in the above list are eight bits wide (each binary digit, that is, a or 1, is called a bit), Mops actually stores numbers on the stack as thirtytwo bit binary numbers. Therefore, even though you type the number 10 (decimal) into the stack, the number is actually stored as:
0000 0000 0000 0000 0000 0000 0000 1010
If you were to calculate how many numbers you could describe within a thirtytwo bit binary number, it would come out to 4294967296, that's over fourbillion. Plenty big for just about every job you'll put your Mac to.
Note: You've probably noticed that we space out binary numbers in groups of four bits. In a computer's memory, bits are stored consecutively, one after the other, but we use this convention to improve readability. For example, is 10000010110001000000 the same number as 10000101100001000000? When you group them in fours, it would be easy to see without hesitating or getting crosseyed that they are not the same numbers.
But, that's fourbillion positive numbers. How do you work with negative numbers?
Signed and Unsigned Numbers
The answer lies in a special technique of Mops that takes the unsigned (positive only) range of fourbillion and divides it into two halves, each slightly more than twobillion numbers. One half is assigned to the positive range, the other half to the negative. In other words, the range of these signed (positive or negative) numbers is plusorminus 2147483647.
What distinguishes a signed from an unsigned number is the way you perform operations on them. For example, if you enter a negative number onto the stack, the minus sign () shows Mops that you intend to use a signed number. If, on the other hand, you were to enter the number three billion onto the stack, Mops would know that you mean it to be an unsigned number, since anything above the plusorminus 2billion range can only be an unsigned number.
But you can force the issue if you want, and convert the designation of a number on the stack for use in arithmetic operations and display purposes.
To understand this process, imagine that you are using a tape recorder that has a digital tape counter that counts in binary. If you set the counter to 0000 0000 and start to rewind the tape, the first thing that shows up on the counter is 1111 1111, which is actually 1 with respect to zero. But if you were to fastforward the tape, the counter's maximum number would also be 1111 1111. That high number would correspond to the fourbillion number of an unsigned number. But as a signed number, 1111 1111 represents the start of counting backwards from zero, that is, 1.
For some handson experience with this concept, consider first that the .
(dot) command you learned in the early sections of this manual was actually a command to display the signed number equivalent of the number on the stack. That means that it can display numbers only within the plusorminus twobillion range. Prove it now by entering threebillion (a 3 and nine zeros) on the stack. Sure enough, the stack display will show:
Stack: depth 1 1294967296
which is a signed number equivalent, a negative number near onebillion.
Conversely, let's enter a 1 (a signed number) onto the stack. This time, however, you want to display it as an unsigned number. To do this, you use the word U.
, which first converts the number to an unsigned number and then types it to the screen.
U.

( n  )

Prints the number on the top of the stack to the screen as an unsigned, singleprecision number. 

U<

( u1 u2  boolean )

Compares two unsigned singleprecision numbers. If 'u1 ' is less than 'u2 ', then leaves TRUE on the stack; otherwise, leaves FALSE.

U>

( u1 u2  boolean )

Compares two unsigned singleprecision numbers. If 'u1 ' is greater than 'u2 ', then leaves TRUE on the stack; otherwise, leaves FALSE.

Try this sequence and watch what happens:
1 U. cr
4294967295
Just to reinforce the difference, now try the same example with 1 using .
instead of U.
.
One Last Set of Numbers; ASCII
You've already had a preview of a set of numbers called ASCII codes. These are numbers that were assigned by an industry standards group to every number, letter, and symbol on the computer keyboard, plus many control codes that computers use to communicate with each other and with peripherals they use (such as printers). ASCII (pronounced "askey") is an acronym for American Standard Code for Information Interchange. It is this standard that allows computers to communicate so effectively over telephone lines and even network connections.
Note: Actually, Mops itself supports Unicode, which is a vastly larger standard that encompasses many languages around the world, as well as formal rules for encoding, manipulating, and displaying those languages. The good news is that you won't generally need to be aware of this difference, since all the characters in the ASCII standard have been included as a subset of the of the Unicode standard. In this manual, consider our use of the term ASCII to be synonymous with that subset of the Unicode standard made up of characters found in the ASCII character set.
When you press the letter 'a' on the keyboard, the computer recognizes the character only as the number 97 (decimal). Because each letter and symbol has a unique number, it is possible to make comparisons of a key pressed and manipulate characters on the screen with the many number crunching tools you've already learned. If you know, for example, that all capital letters of the alphabet are numbered from 65 to 90, it is possible to create a DO
...LOOP
that instantly prints those letters on the screen:
: ALPHABET 91 65 DO i emit cr LOOP ;
EMIT
is a Mops word that displays on the screen the character that is referenced by its ASCII number. If you want to put a particular ASCII character value on the stack, you can use the Mops word &
("ampersand"). Try typing:
& c . cr
99
and you'll see that the stack display shows 99, which is the ASCII value for 'c'. Other Mops words that might go along with EMIT
and &
are:
EMIT

( n  )

Displays the character referenced by ASCII number, ‘n ’.


SPACE

(  )

Displays a blank space on the screen. 
SPACES

( n  )

Displays ‘n ’ blank spaces on the screen.

Here's a use of SPACES
in a modified alphabet definition to demonstrate its power:
: ALPHABET2 91 65 DO i dup 64  spaces emit cr LOOP ;
It is also convenient to remember that upper and lowercase letters are separated by a factor of 32, regardless of the letter. This may come in handy when you need to convert upper to lower cases or vice versa.
Lesson 13  Tutorial  Lesson 15 
Documentation 