12.19Fixed point calculation. 4tH 4tH Forth compiler
Publicitate
Publicitate
CHAPTER 12. STANDARD LIBRARIES 189
; if ( a n x) drop ." Found " 2r> .name cr else ( a n x)
>next 2r> recurse then else
( a n x a n)
( --)
( a n x) drop 2r> .name ." not found" cr then ( --)
: >name -rot 2>r >surname 2r> >first ;
: demo s" Ritchie" s" Dennis" people >name s" Moore" s" Chuck" people >name s" Lovelace" s" Ada" people >name
; demo \ run the demo
”>NAME” is a wrapper around this programs most important words ”>SURNAME” and
”>FIRST”. ”>SURNAME” simply searches for a given surname in the table and returns its address. ”>FIRST” takes over and compares the first name. If it checks out we’re done, if not it calls ”>NEXT”. ”>NEXT” increments the pointer, so it now points to the next row.
Then it calls ”>SURNAME” again, effectively continuing the search. Finally ”>FIRST” calls itself to check the first name again. Depending on the contents of the table, this process can be repeated several times.
12.19
Fixed point calculation
We already learned that if we can’t calculate it in dollars, we can calculate it in cents. And still present the result in dollars using pictured numeric output:
: currency <# # # [char] . hold #s [char] $ hold #> type cr ;
In this case, this:
200012 currency
Will print this:
$2000.12
Well, that may be a relief for the bookkeepers, but what about us scientists? You can do the very same trick. We have converted some Forth code for you that gives you very accurate results. You can use routines like SIN, COS and SQRT. A small example:
[needs lib/math.4th]
45 sin . cr
You will get "7071", because the result is multiplied by 10000. You can correct this the same way you did with the dollars: just print the number in the right format. You can also use a delightful little library created by Leo Brodie called ”fraction.4th”. This library allows you to do arithmetic in the range of -13.1072 and 13.1071 with a precision of 0.0001! It seamlessly integrates with the ”math.4th” library:
CHAPTER 12. STANDARD LIBRARIES 190
[needs lib/math.4th]
[needs lib/fraction.4th]
45 sin s>v v. cr
This one will actually print:
0.7071
Of course, you can also use it with other math words, as long as they are properly scaled.
The scaling constant is called ’10K’ and is available from ”constant.4th”. The nice thing about fractions is that you can do all basic math (within its range, of course) without bothering about the decimal point. To convert a fixed point number to a fraction, you have to multiply it by ’10K’, which is 10,000 and call ’S>V’, e.g. in order to convert ’0.7071’ to a fraction you need to do this:
7071 s>v
You can also define a fraction yourself, e.g. this converts two-thirds to a fraction:
2 3 v/
You can add or subtract fractions, e.g.:
7071 s>v 2 3 v/ - v. cr
This is equivalent to:
PRINT 0.7071 - 0.6666
You can multiply or divide fractions, e.g.:
7071 s>v 2 3 v/ v* v. cr
This is equivalent to:
PRINT 0.7071 * 0.6666
Since a fraction is still a single-cell number, you can manipulate the stack in the usual way.
In some cases you can even mix cells and fractions, as the following table will show you:
With the word ’V>S’ you can convert a fraction back to a ’10K’ scaled fixed point number.
You can print a fraction using the word ’V.’.
Another example is SQRT from ”math.4th”. If you enter a number of which the root is an integer, you will get a correct answer. You don’t even need a special formatting routine. If you enter any other number, it will return only the integer part. You can fix this by scaling the number.
However, scaling it by 10 will get you nowhere, since "3" is the square root of "9", but "30" is not the square root of "90". In that case, we have to square the scale itself; we need 100,
10,000 or even 1,000,000 to get a correct answer. In order to retrieve the next digit of the square root of "650", we have to multiply it by 100, which is the square of 10:
Descarcă
Publicitate