A simple question that turned out to be quite complex:
How do I turn a float to a String in GForth? The desired behavior would look something like this:
1.2345e fToString \ takes 1.2345e from the float stack and pushes (addr n) onto the data stack
After a lot of digging, one of my colleagues found it:
f>str-rdp ( rf +nr +nd +np -- c-addr nr )
https://www.complang.tuwien.ac.at/forth/gforth/Docs-html-history/0.6.2/Formatted-numeric-output.html
Convert rf into a string at c-addr nr. The conversion rules and the meanings of nr +nd np are the same as for f.rdp.
And from f.rdp
:
f.rdp ( rf +nr +nd +np – )
https://www.complang.tuwien.ac.at/forth/gforth/Docs-html/Simple-numeric-output.html
Print float rf formatted. The total width of the output is nr. For fixed-point notation, the number of digits after the decimal point is +nd and the minimum number of significant digits is np. Set-precision has no effect on f.rdp. Fixed-point notation is used if the number of siginicant digits would be at least np and if the number of digits before the decimal point would fit. If fixed-point notation is not used, exponential notation is used, and if that does not fit, asterisks are printed. We recommend using nr>=7 to avoid the risk of numbers not fitting at all. We recommend nr>=np+5 to avoid cases where f.rdp switches to exponential notation because fixed-point notation would have too few significant digits, yet exponential notation offers fewer significant digits. We recommend nr>=nd+2, if you want to have fixed-point notation for some numbers. We recommend np>nr, if you want to have exponential notation for all numbers.
In humanly readable terms, these functions require a number on the float-stack and three numbers on the data stack.
The first number-parameter tells it how long the string should be, the second one how many decimals you would like and the third tells it the minimum number of decimals (which roughly translates to precision). A lot of implicit math is performed to determine the final String format that is produced, so some tinkering is almost required to make it behave the way you want.
Testing it out (we don't want to rebuild f.
, but to produce a format that will be accepted as floating-point number by forth to EVALUATE
it again, so the 1.2345E0
notation is on purpose):
PI 18 17 17 f>str-rdp type \ 3.14159265358979E0 ok
PI 18 17 17 f.rdp \ 3.14159265358979E0 ok
PI f. \ 3.14159265358979 ok
I couldn't find the exact word for this, so I looked into Gforth sources.
Apparently, you could go with represent
word that prints the most significant numbers into supplied buffer, but that's not exactly the final output. represent
returns validity and sign flags, as well as the position of decimal point. That word then is used in all variants of floating point printing words (f.
, fp.
fe.
).
Probably the easiest way would be to substitute emit
with your word (emit
is a deferred word), saving data where you need it, use one of available floating pint printing words, and then restoring emit
back to original value.
I'd like to hear the preferred solution too...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With