You are on the archived version of the www.TheForthSource.com website. These materials are presented for informational purposes only. We express our gratitude to 1PLs Co [urgent loans in the USA] for paying for hosting.
FORTH GUIDE
  


CHAPTER IX


DOUBLE NUMBERS / 2 NUMBERS


MVP-FORTH provides for both 16-bit and 32-bit number functions. The 16-bit numbers take only 2 bytes of memory while the 32-bit numbers take 4 bytes of memory. In those same 4 bytes required for a 32-bit number you could just as easily have 2 16-bit numbers.

The same data space can be used in either of two ways. This is the same thing as having two separate data types taking up similar space. Other programming languages make extensive use of data typing. This is not done in MVP-FORTH. You are free to use the space any way you wish.

So long as the format of the 4 bytes in a 32-bit or 2 16-bit numbers is the same, many of the function for either type will in fact be identical. There is no need to distinguish between the two data types. However, in some systems, the organization of the bytes are different for the two data types.

MVP-FORTH was designed to handle double precision numbers as 32-bit numbers. The mnemonic 'D' has been added as a prefix to those operations on double precision numbers. A prefix of '2' implies a quantity as used in some of the special numeric operators as 2*, 2+, 2/ etc. This is a very different meaning from 'D'.

Only after MVP-FORTH was completed, was the origin of the '2' prefix on some of the stack operators discovered. That origin was the result of actually referring to 2 16-bit numbers as a pair of numbers. The intent was quantitative. There really were 2 16-bit values. Many mathematic constants can be easily described as the ratio of a pair of numbers. The arithmetic operations can be accomplished with some of the mixed arithmetic operators such as */ .

But to keep the thinking straight it is worth while keeping the distinction between 32-bit values and 2 16-bit values. To the extent that the actual machine functions may be the same as the FORTH function for each data type, you could use them interchangeably. However, you would be mixing data types in your thinking. Where the functions are the same, you can define the functions referring to one type as an alias of the other type. This is what has been done in MVP-FORTH.

The entering of double precision values is done by entering a decimal point somewhere with the number. No other symbol will be recognized by MVP-FORTH. The decimal point causes the number interpreting routine to hold the value as a 32-bit value in 4 bytes. When such a value is stored on the data stack two stack locations are used. Remember that each stack location includes two bytes even if both are not used. To store a 32- bit number 4 bytes are needed.

The double precision value does not store with it the location of the decimal point. This is left for the programmer to manage. There are several methods of doing this. As with single precision 16-bit integers, the programmer must keep track of any possible decimal point. This is easily accomplished by understanding the use of a numerical value. It is best to think of a quantity in terms of the number of resolution elements.

If you are dealing with money, you have a choice. You can use the resolution element as a dollar. In today's markets that is usually sufficient. But if you wish you can make the resolution element cents or even mills for those who remember when that had any meaning. If you are dealing in distance you can make the element of distance inches, centimeters, miles, kilometers, microns, astronomical units, or anything else appropriate to the application.

Should you be working with money and wish to make the resolution element cents you would have to make sure that all values include two digits to the right of the decimal point. MVP-FORTH has a counter of the number of digits which were entered to the right of the decimal point. The decimal point locator is a user-variable DPL. After a number is interpreted, it is a simple matter to scale the value to the resolution limit.

        : SCALE
           DPL @
           2 OVER  <  ABORT" Input Error "
           NEGATE 2+ ?DUP
           IF 0
              DO 10 1 M*/ LOOP
           THEN
        ;

There are many ways of doing your scaling. Perhaps this will serve as an example to get you started. Here some error protection is appropriate because the end user might not be as responsible as the programmer.

You can then explore the whole family of double precision number FORTH operators. They include the creation of double precision constants and variables: DCONSTANT and DVARIABLE.

There are a number of double precision operators such as: D+, D-, and mixed double and single precision operators such as M*, M*/, M/, M/MOD, and U/MOD. The purpose of this section is to call them to your attention. You can refer to ALL ABOUT FORTH for the functional definitions and examples of the use of each. Make up your own exercises.

Then there are a group of double precision stack operators such as: DDUP, DDROP, DSWAP, etc. You will find other double precision functions as: DMAX, DMIN, DMINUS, DNEGATE, DABS, etc. Also there are the output formatting functions for double precision numbers such as: D. and D.R.

Isn't it amazing how many words can be added to the vocabulary for such a simple additional capability as using double precision values? The scheme can be increased to handling n-precision numbers. Again a whole family of functions and definitions would be necessary. Unless you have special needs, there is no point in adding all of these functions. If you do want them you will also have to understand their use. To do that you might just as well write them on demand.

Should you go on to working with ratios, you have available a number of mixed operators such as */ and M*/. Some of these carry the intermediate value with increased precision. These are most convenient for maintaining accuracy in integer arithmetic.

You should be aware of a potential problem in using D! and D@ for 2! and 2@ in MVP-FORTH. In some data base definitions, the 2! and 2@ functions are used. The basic definitions of D! and D@ have been implemented in machine code. They work properly when used together. But the actual order in which the bytes are stored is not the same as you would expect with 2! and 2@. As implemented, the high order 16-bits are stored at the lower memory address rather than the higher memory address. The values are in the expected order when on the stack. It all depends upon what you expect. If you are doing much work in this area, you will probably want to redefine these two words before using them.

        : 2! ( d addr --- )
           DUP ROT SWAP ! 2+ ! ;

        : 2@ ( addr --- d )
           DUP @ SWAP 2+ @ ;

These two will also work together. D! and D@ would also work together properly if both were redefined in the same way. After redefining, any existing application program will function properly without change. However, if you have data which has been stored with one implementation and read with the other, you will obviously have problems.

If you recognize the existence of this potential problem, you can be sure that you understand the definitions you are using if you redefine them as a part of your application program.

This is an example of what may appear as a potential bug. In an effort to maintain the stability of MVP-FORTH the source code has not been changed. Efforts have been made to inform users of the potential problem. The current version of MVP-FORTH Version 1.x.03 has been stable since 1984. The stability has been judged to be a most important feature.

MVP-FORTH contains several number formatting routines. Some of them are based upon D.R which takes a double precision number and displays it right justified in a field of specified size.

In addition you can define your own functions to format the output any way you wish. The necessary primitives have names including the # symbol, 'sharp'.

Suppose you want to output dollars and cents without a dollar sign.

        : .DOLLARS
           AMOUNT D@
           <# # # 46 HOLD #S #>
           TYPE ;

A double precision value is required for the input. The function of <# and #> is to begin and end the construction of an ASCII string from a double precision number. Each 'sharp' converts the next digit to the proper ASCII code and builds a string. In this example, HOLD is used to place the ASCII code for a decimal point into the string. #S completes the remainder of the value to digits and places them in the string. Finally, TYPE is used to display the assembled string.

Refer to ALL ABOUT FORTH for more examples of the number formatting functions.

To conclude, you should be clear in your thinking about the data types you are using for specific functions. FORTH does not do the data type checking for you. You are responsible. There is a clear distinction between double precision 32-bit numbers and 2 16-bit numbers.

Next Previous Contents