123456. <# # # ASCII . HOLD #S ASCII $ HOLD #> TYPE (displays $1234.56)
In this example, we use PNO to format a double number into dollars and cents by simply adding the appropriate characters into the PNO string in the correct places.
The first two digits of the value are converted manually using #. Then a decimal place is added using ASCII to obtain the ASCII value of the period character, and HOLD to physically insert it into the PNO buffer. #S is then used to convert the rest of the number to PNO format. Finally, a dollar sign is added to the PNO string.
It is, of course, possible to use this as a basis for displaying any double value in a numeric format:
: .$ <# # # ASCII . HOLD #S ASCII $ HOLD #> TYPE ;
The above definition will display any double value as a correctly formatted currency value in dollars and cents:
Example:
9984751. .$ (displays $99847.51)
1. .$ (displays $0.01)
It should be noted that it is perfectly possible to mix normal Forth code within <# … #> blocks. Indeed, all the words introduced such as # #S HOLD etc. are normal Forth colon definitions. Looping, and IF ...THEN constructs are all allowed. For example, the following code will correctly display large numeric values, correctly formatted with commas, regardless of the size of the number:
: .$ ( ud:value – ) <# # # ASCII . HOLD BEGIN 2DUP 999. D> WHILE # # # ASCII , HOLD REPEAT #S ASCII $ HOLD #> TYPE ;
123456. .$ (displays $1,234.56)
1234567. .$ (displays $12,345,67)
12345678. .$ (displays $123,456.78)
123456789. .$ (displays $1,234,567.89)
Using the above, it is simple to perform fast and accurate math using currency. Floating point is not required; indeed floating point could introduce inaccuracies when dealing with currency values (especially if any sort of division is performed). Since we are dealing with double precision numbers, which can range from -2,147,483,648 to 2,147,483,647 (signed) or 0 to 4,294,967,295 (unsigned) we have plenty of magnitude available for most general purpose applications.
|