Applesoft uses a different floating representation than the routines in the wozfp3.txt file, so those Applesoft routines won't quite do the trick.
You can look at how EhBASIC does it (LAB_2887 and LAB_296E) for hints. Here's the idea:
To convert a string such as -123.45E-67 which is -123.45 * 10 ^ -67:
1. Initialize M to 0. M is a FP number.
2. Accumulate the mantissa digits. Work left to right using M = M * 10 + digit until you get to the exponent.
3. Count the number of digits after the decimal point and call this count K. K is a 1-byte signed integer.
4. Initialize N to zero. N is a 1-byte signed integer.
5. Accumulate the exponent digits. Work left to right using N = N * 10 + digit.
6. If there was a minus sign before the exponent (i.e. after E) then negate N, i.e. N = -N.
7. The number we want is M * 10 ^ (N-K), so start with M.
8. If N-K is less than zero, divide by 10 ^ (K-N), which you can do by dividing by 10 (K-N) times.
9. If N-K is greater than zero, multiply by 10 ^ (N-K), which you can do by multplying by 10 (N-K) times.
10. If there was a minus sign before the manitissa, negate the result.
It's not terrific, but it's okay.
In the example -123.45E-67, M = 12345, K = 2, and N = -67. N-K is less than zero, so dividing by 10^-69 is 1.2345 * 10 ^ -65 which is negated to give the correct result, -1.2345 * 10 ^ -65.
You may wish to put some limit on the maximum number of mantissa digits that are accumulated. In EhBASIC 1.000 works as you would expect, but if you put 50 zeros after the decimal point you'll get an overflow error, because M = 10^50 which is a larger number than EhBASIC can handle.
To output an FP number, you'll have to decide the maximum number of mantissa digits to output. Here's the idea for outputing a FP number N in scientfic notation, where D is the maximum number of mantissa digits, and 10 ^ M < 2 ^ 23:
1. If N is zero, output a zero and end.
2. If N is negative, output a minus sign and negate N
3. Initialize K to 0, K is a 1-byte signed integer.
4. If N < 10 ^ (D-1), then multiply N by 10 until N >= 10 ^ (D-1), and decrement K each time you multiply by 10.
5. If N >= 10 ^ D, then divide by 10 until N < 10 ^ D, and increment K each time you divide by 10.
6. With N in FP1 (i.e. the mantissa in FP1 and the exponent in X1) shift M1 right (150-X1) times. Now M1 contains a 3-byte (unsigned) integer (M1+0 is the high byte, M1+2 is the low byte), and 10 ^ (D-1) <= M1 <= 10 ^ D.
7. output the integer in M1, but put a decimal point between the first and second digit, then output "E", then the signed intger K+D-1.
Example: N = 12, D = 6
Multiply 12 by 10 4 times, so K = -4 and FP1 = 120000 (100000 <= 120000 < 1000000). X1 = 148 and M1 = $75300, so shift M1 right twice to get M1 = $1D4C0 = 120000. K+D-1 = -4+6-1 = 1, so the output is 1.20000E1.
Again, not terrific, but okay.
The idea for a routine that outputs a number without an "E" followed by an exponent, is to replace step 7 with:
7. If K < 1-D, output a decimal point, then output -K-D zeros, then the integer M1.
8. If 1-D <= K < 0, output the integer M1, but put a decimal point between the (K+D)th digit and the (K+D+1)th digit.
9. If K >= 0, output the integer M1, followed by K zeros.
In example above, D = 6, and K = -4, so 0 <= K+D-1 < D-1, the decimal point is between the 2nd and 3rd digits, and the output is 12.0000.
Once you get the above working, you can add other features.
Note that a number like .1 cannot be represented exactly even though it can be entered in a string exactly. It the same idea as 1/3 which is approximately .333333 but not exactly .333333. So if you convert a number and immediately output it, the output may be a slightly different number than the input. For this reason, you may wish to consider using BCD FP routines likes DP18 or KIMATH, both of which can represent .1 exactly. Their input and output routines are much simpler.
I haven't tested all of the above, so it may need some tweaking, but it should be enough to get started.
|