Closed tingtron closed 1 year ago
Once again, great test cases! Pretty printing floating point numbers is surprisingly challenging. These test cases should help get it sorted. I'll include this test in the next release, too.
Yes, in many cases the particular formatting approach depends on the goal. I vaguely recall working with sprintf
and crafting the format strings for it and then adding or removing trailing zeros manually -- for a particular consistent look within different ranges in a visualization or a report.
In Apple Numerics 2nd ed, they showed Dec2Str. Interesting how that would look like and if there are sources for those routines. I haven't found yet. (Also don't know if the ORCA sources have it.)
In the case of RPN calculator, the requirements are to fit within the display width; maximize visible significant digits and follow a selected fixed number of decimals.
One question how is the intdigits
supposed to be used? And is it more useful than a displayWidth
parameter instead?
In the approach in ext2str
(fpstr) is reasonable by using and adapting Bin2Dec
(aka Ext2Dec
or Num2Dec
). One problem I see is using the DecForm.style=1 (Fixed) even for a "fixed" decimal format in calculator fashion -- without losing small decimals, and when dealing with large exponents and many significant digits.
So I am thinking it makes sense to always use DecForm.style=0 (Float), and then based on exponent and display width decide whether to use the Exp. format or keep non-Exp. format (unless explicit FPSTR_EXP is requested).
In addition, in case non-exp. choice above, in case of FPSTR_FLOAT, all fractionals would be kept, whereas for FPSTR_FIXED, the fractionals would be either rounded or padded with zeors (depending on FPSTR_STRIP). For FPSTR_FIXED this fractional dressing could be done manually or by invoking Bin2Dec
a second time, but with DecForm.style=1 (Fixed).
The reason for this two-stage processing and initial Bin2Dec
call with DecForm.style=0 (Float) is to obtain the Exp. to make the above decisions. Alternatively, the Exp. from the ext
representation could be accessed directly -- not sure if there's a SANE call for that or could be just read from memory (but it's not very trivial, and may have to deal with de-normalized representation,)
This example FPSANE.PLA shows which sizes of exp are candidates for float and exp representation. The output here is:
<input string>
[len] <sig> e<exp> dp=<decimal pos.>
/PLASMA/BLD/:+fpsane
Float Format: disp.width=16 frac=6
....|....|....|....|....|....|....|....
123456789.1234E+1000
[14] 12345678912340 e995 dp=1009
1.123456789012E+1000
[14] 11234567890120 e987 dp=1001
123456789.12345E+100
[14] 12345678912345 e95 dp=109
123456789.123456E+10
[14] 12345678912346 e5 dp=19
12345678901234567890
[14] 12345678901235 e6 dp=20
1234567890.123456789
[14] 12345678901235 e-4 dp=10
12345.12345678901234
[14] 12345123456789 e-9 dp=5
0.000000000123456789
[14] 12345678900000 e-32 dp=-18
0.12345678901234E-10
[14] 12345678901234 e-24 dp=-10
Another issue, but in str2ext, when parsing:
Numbers in the form 0.0dddd
get their exponent doubled. So
0.01
-> 0.001
0.001
-> 0.00001
0.0001
-> 0.0000001
This can be seen in the RPN Calc:
I've made wholesale updates tp FPSTR to address most of the issues you brought up. Rounding will be up to the SANE library, but everything else should be working. I decided to add an additional flag to ext2str to switch to exponential form if overflow/underflow occurs with the FPSTR_FLOAT or FPSTR_FIXED flags. However, I could revert to the case where it is done automatically in the over/underflow cases. Just wasn't sure the best approach would be. I think the additional flag is more flexible (and the flag is called FPSTR_FLEX) to give the option.
I've updated the plasma.2mg image with the latest if you want to check it out.
Summary of issues:
1.23E+10
should not be returned as1.23E+1
E
should be properly rounded. (Observed: it is simply truncated. E.g.1234567
with frac=5 becomes 1.23456E+06 instead of 1.23457E+06.10^-f
(fractional digits), it should automatically switch to exp. form (observed: with frac=40.00001
returns0.0000
instead of1.0000E-05
.123456789.123E+200
should return1.23456789E+208
[16 digits] instead of1.2345678912E+208
[18 digits])Using FPPOW.PLA with different variations of
ext2str
and multipliers:To compare, some rules observed from HP-42s (using Free42):
1) Prioritize Int part over fixed decimals (if Int part fits into Display digits, truncate the fractional digits)
2) Use positive Exp. when Int. part won't fit in Display digits.
3) Use negative Exp. when the value is less than 10^(-FracDigits), if otherwise all frac digits would be zero
4) In Exp. form, the number of decimal digits is observed.
5) In Exp. form, limit Decimal digits <= Disp.digits - Exp digits - 4 (=sign + period + "E+") (This is not an issue in 42s because it has max Fix 11 and 16 Display digits)