...
Don't hide your tools (Moore). I agree. If an implementations of
a language is not good for programming, it is good for nothing.
The "internal" words of an implementation should be helpful to
generate advanced features.
On 20/09/2026 12:37 am, albert@spenarnc.xs4all.nl wrote:
...
Don't hide your tools (Moore). I agree. If an implementations of
a language is not good for programming, it is good for nothing.
The "internal" words of an implementation should be helpful to
generate advanced features.
... I've posted in the past that
numeric string output was a serious omission that forth users have been paying ever since. The argument one can reinvent them doesn't wash.
Nor does it work in the case of non-trivial cases e.g. floating point.
Once you have a proper REPRESENT then it's not hard to write functional string output words for floating point numbers. I've only recently implemented REPRESENT in kForth-32/64/Win32, so I will now go back and rewrite my floating point string output words in my strings library (strings.4th) to use it.
On 9/19/26 21:37, dxf wrote:
On 20/09/2026 12:37 am, albert@spenarnc.xs4all.nl wrote:...
...
Don't hide your tools (Moore). I agree. If an implementations of
a language is not good for programming, it is good for nothing.
The "internal" words of an implementation should be helpful to
generate advanced features.
...-a I've posted in the past that
numeric string output was a serious omission that forth users have been
paying ever since.-a The argument one can reinvent them doesn't wash.
Nor does it work in the case of non-trivial cases e.g. floating point.
I suppose REPRESENT was supposed to be that universal factor for floating point strings, but it is not implemented properly in some, probably many Forth systems. It is not easy to implement as dtoa() shows, requiring big number arithmetic.
Once you have a proper REPRESENT then it's not hard to write functional string output words for floating point numbers. I've only recently implemented REPRESENT in kForth-32/64/Win32, so I will now go back and rewrite my floating point string output words in my strings library (strings.4th) to use it.
On 20/09/2026 12:37 am, albert@spenarnc.xs4all.nl wrote:
...
Don't hide your tools (Moore). I agree. If an implementations of
a language is not good for programming, it is good for nothing.
The "internal" words of an implementation should be helpful to
generate advanced features.
The factoring of forth words leads to an explosion of words - some
generally useful and others perhaps not. In my kernel there are
currently 707 words of which 143 are headerless. Years of use has
seen little change suggesting my predictions in relations of goals
were mostly correct. It's 143 words I don't have to formally document.
I suppose REPRESENT was supposed to be that universal factor for
floating point strings,
but it is not implemented properly in some,
probably many Forth systems. It is not easy to implement as dtoa()
shows, requiring big number arithmetic.
Once you have a proper REPRESENT then it's not hard to write functional >string output words for floating point numbers.
On 20/09/2026 12:37 am, albert@spenarnc.xs4all.nl wrote:
...
Don't hide your tools (Moore). I agree. If an implementations of
a language is not good for programming, it is good for nothing.
The "internal" words of an implementation should be helpful to
generate advanced features.
The factoring of forth words leads to an explosion of words - some
generally useful and others perhaps not. In my kernel there are
currently 707 words of which 143 are headerless. Years of use has
seen little change suggesting my predictions in relations of goals
were mostly correct. It's 143 words I don't have to formally document.
A different implementer may well see things differently but that's
not my concern.
On 20/09/2026 1:15 pm, Krishna Myneni wrote:
On 9/19/26 21:37, dxf wrote:
On 20/09/2026 12:37 am, albert@spenarnc.xs4all.nl wrote:...
...
Don't hide your tools (Moore). I agree. If an implementations of
a language is not good for programming, it is good for nothing.
The "internal" words of an implementation should be helpful to
generate advanced features.
...-a I've posted in the past that
numeric string output was a serious omission that forth users have been
paying ever since.-a The argument one can reinvent them doesn't wash.
Nor does it work in the case of non-trivial cases e.g. floating point.
I suppose REPRESENT was supposed to be that universal factor for floating point strings, but it is not implemented properly in some, probably many Forth systems. It is not easy to implement as dtoa() shows, requiring big number arithmetic.
Well, ANS REPRESENT has issues beyond big number arithmetic:
In article <6aaf4707$1@news.ausics.net>, dxf <dxforth@gmail.com> wrote:
On 20/09/2026 12:37 am, albert@spenarnc.xs4all.nl wrote:
...
Don't hide your tools (Moore). I agree. If an implementations of
a language is not good for programming, it is good for nothing.
The "internal" words of an implementation should be helpful to
generate advanced features.
The factoring of forth words leads to an explosion of words - some
generally useful and others perhaps not. In my kernel there are
currently 707 words of which 143 are headerless. Years of use has
seen little change suggesting my predictions in relations of goals
were mostly correct. It's 143 words I don't have to formally document.
A different implementer may well see things differently but that's
not my concern.
Maybe ciforth is a brilliant design then. An explosion of words
is to be avoided.
The most useless (not absolutely useless) words in the kernel are
imposed by the standard.
CHAR ( u -- char ) factor of #
DIGIT ( char radix -- u true | char false ) factor of >NUMBER
Krishna Myneni <krishna.myneni@ccreweb.org> writes:
I suppose REPRESENT was supposed to be that universal factor for
floating point strings,
It mostly is, but when I implemented F.RDP, I found that it is
cumbersome for converting into a string with a given number of digits
behind the decimal point. REPRESENT is modeled on C's ecvt(), but C
also has fcvt() which is designed for that purpose:
| The fcvt() function is identical to ecvt(), except that ndigits
| specifies the number of digits after the decimal point.
So having a Forth word modeled after fcvt() would have been useful;
OTOH, I managed to do without it, and I only have one use for the fcvt()-based word, so maybe it is good enough as it is.
For multi-threaded execution, use ecvt_r() and fcvt_r() instead (with
glibc).
All these functions have been deprecated, and sprintf() is
recommended. My guess is that POSIX destandardized ecvt() and fcvt()
because of thread-safety, and they did not want to standardize
ecvt_r() and fcvt_r() because they considered the already-standard
sprintf() good enough. The glibc probably decided to deprecate
ecvt_r() and fcvt_r() because sprintf() is considered good enough.
but it is not implemented properly in some,
probably many Forth systems. It is not easy to implement as dtoa()
shows, requiring big number arithmetic.
It seems that you think about producing the closest mantissa string
that fits in the provided buffer. And if I read the specification of REPRESENT, that's what it requires. However, given the implementation
cost, especially on small systems, that looks like a pretty high bar
to me. Interestingly, the Linux man page on ecvt() states:
|[...] string of ndigits digits (where ndigits is reduced to a |system-specific limit determined by the precision of a double)
and I guess it takes this wording from the POSIX wording (I am too
lazy to look it up) or maybe an older glibc documentation (the current
one does not contain this wording).
Once you have a proper REPRESENT then it's not hard to write functional>> string output words for floating point numbers.
Even when only the first 16 digits or so are correct, it's very
useful, and most uses don't notice the difference.
On 20/09/2026 1:15 pm, Krishna Myneni wrote:...
On 9/19/26 21:37, dxf wrote:
C's equivalent primitives ecvt() etc were never standardized - presumably on the basis sprintf() sufficed. The latter piqued my interest such that for over
a decade I've looked for cases that expressly required REPRESENT. Thus far (FS.) (FE.) (F.) have proven sufficiently primitive. In any case I'll be looking
forward to your use cases. I want to know whether my premise is correct.
On 9/20/26 1:01 AM, dxf wrote:
On 20/09/2026 1:15 pm, Krishna Myneni wrote:What are these issues?
On 9/19/26 21:37, dxf wrote:
On 20/09/2026 12:37 am, albert@spenarnc.xs4all.nl wrote:...
...
Don't hide your tools (Moore). I agree. If an implementations of
a language is not good for programming, it is good for nothing.
The "internal" words of an implementation should be helpful to
generate advanced features.
...-a I've posted in the past that
numeric string output was a serious omission that forth users have been >>>> paying ever since.-a The argument one can reinvent them doesn't wash.
Nor does it work in the case of non-trivial cases e.g. floating point.
I suppose REPRESENT was supposed to be that universal factor for floating point strings, but it is not implemented properly in some, probably many Forth systems. It is not easy to implement as dtoa() shows, requiring big number arithmetic.
Well, ANS REPRESENT has issues beyond big number arithmetic:
...
dtoa() is the primitive for REPRESENT -- it provides exactly the same return information as specified in the standard for REPRESENT, and it is used in the implementation of binary floating point to decimal string conversions in various computer languages. glibc functions provide conversions consistent with dtoa().
--
Krishna
On 20/09/2026 11:25 pm, Krishna Myneni wrote:
On 9/20/26 1:01 AM, dxf wrote:
On 20/09/2026 1:15 pm, Krishna Myneni wrote:What are these issues?
On 9/19/26 21:37, dxf wrote:
On 20/09/2026 12:37 am, albert@spenarnc.xs4all.nl wrote:...
...
Don't hide your tools (Moore). I agree. If an implementations of
a language is not good for programming, it is good for nothing.
The "internal" words of an implementation should be helpful to
generate advanced features.
...-a I've posted in the past thatI suppose REPRESENT was supposed to be that universal factor for floating point strings, but it is not implemented properly in some, probably many Forth systems. It is not easy to implement as dtoa() shows, requiring big number arithmetic.
numeric string output was a serious omission that forth users have been >>>>> paying ever since.-a The argument one can reinvent them doesn't wash. >>>>> Nor does it work in the case of non-trivial cases e.g. floating point. >>>>
Well, ANS REPRESENT has issues beyond big number arithmetic:
...
- does not specify exponent value (n) in the case of 0.0E .
- nothing stated regarding values for n and flag1 when flag2 is false.
- nothing stated regarding the graphic string's length, alignment orfailed. You need more information about the floating point format to do anything, which is not specified in the standard.
padding, when flag2 is false.
It is implementation dependent. The flag tells you your conversion has
- no provision for rounding entire significand.What do you mean by rounding the *entire* significand? For IEEE doubleprecision, the significand can have in excess of 750 digits for the
The last two being the worst.
On 9/20/26 2:35 AM, Anton Ertl wrote:...
It mostly is, but when I implemented F.RDP, I found that it is
cumbersome for converting into a string with a given number of digits
behind the decimal point. REPRESENT is modeled on C's ecvt(), but C
also has fcvt() which is designed for that purpose:
I will be
reimplementing F.RD using REPRESENT so maybe I will see what you found >cumbersome about it.
Common usage names for the conversion to various decimal string formats >would be nice, however.
All these functions have been deprecated, and sprintf() is
recommended. My guess is that POSIX destandardized ecvt() and fcvt()
because of thread-safety, and they did not want to standardize
ecvt_r() and fcvt_r() because they considered the already-standard
sprintf() good enough. The glibc probably decided to deprecate
ecvt_r() and fcvt_r() because sprintf() is considered good enough.
I tried to use sprintf() for a floating point to string conversion
recently and I realized that I would have to do some string processing >myself. It's not nearly as flexible as REPRESENT.
...I think maybe what you are asking for is a different REPRESENT for small systems which can't afford the cost of complying with the current standard. That's a reasonable request.
On 21/09/2026 2:10 am, Krishna Myneni wrote:
...I think maybe what you are asking for is a different REPRESENT for small systems which can't afford the cost of complying with the current standard. That's a reasonable request.
AFAICS ANS neither required - nor excluded - a 750 digit REPRESENT.
What REPRESENT does exclude - if one accepts the interpretation of many
an implementer - is the ability to handle the following scenarios.
0.9e 0 (f.) type 1. ok
0.4e 0 (f.) type 0. ok
1 set-precision ok
0e 0e f/ (fs.) type -NAN ok
For my part, I considered it enough of a problem to do something about it.
On 21/09/2026 2:10 am, Krishna Myneni wrote:
...I think maybe what you are asking for is a different REPRESENT for small systems which can't afford the cost of complying with the current standard. That's a reasonable request.
AFAICS ANS neither required - nor excluded - a 750 digit REPRESENT.
What REPRESENT does exclude - if one accepts the interpretation of many
an implementer - is the ability to handle the following scenarios.
0.9e 0 (f.) type 1. ok
0.4e 0 (f.) type 0. ok
1 set-precision ok
0e 0e f/ (fs.) type -NAN ok
For my part, I considered it enough of a problem to do something about it.
On 9/20/26 10:02 PM, dxf wrote:
On 21/09/2026 2:10 am, Krishna Myneni wrote:
...I think maybe what you are asking for is a different REPRESENT for small systems which can't afford the cost of complying with the current standard. That's a reasonable request.
AFAICS ANS neither required - nor excluded - a 750 digit REPRESENT.
What REPRESENT does exclude - if one accepts the interpretation of many
an implementer - is the ability to handle the following scenarios.
-a-a 0.9e 0 (f.) type 1. ok
-a-a 0.4e 0 (f.) type 0. ok
-a-a 1 set-precision-a ok
-a-a 0e 0e f/ (fs.) type -NAN ok
For my part, I considered it enough of a problem to do something about it. >>
Show me what is being passed to REPRESENT for the above examples. I don't disagree there may be a problem. I can't see it from your examples since it doesn't show how REPRESENT is being used.
On 21/09/2026 1:43 pm, Krishna Myneni wrote:
On 9/20/26 10:02 PM, dxf wrote:
On 21/09/2026 2:10 am, Krishna Myneni wrote:
...I think maybe what you are asking for is a different REPRESENT for small systems which can't afford the cost of complying with the current standard. That's a reasonable request.
AFAICS ANS neither required - nor excluded - a 750 digit REPRESENT.
What REPRESENT does exclude - if one accepts the interpretation of many
an implementer - is the ability to handle the following scenarios.
-a-a 0.9e 0 (f.) type 1. ok
-a-a 0.4e 0 (f.) type 0. ok
-a-a 1 set-precision-a ok
-a-a 0e 0e f/ (fs.) type -NAN ok
For my part, I considered it enough of a problem to do something about it. >>>
Show me what is being passed to REPRESENT for the above examples. I don't disagree there may be a problem. I can't see it from your examples since it doesn't show how REPRESENT is being used.
Here are the three cases. Breakpoints were inserted immediately before/after REPRESENT. Comments added.
0.9e 0 (f.) \ round r to 0 decimal places, output as a string
<BREAK> stack= 8551 0 < \ input to REPRESENT
<ok> go
<BREAK> stack= 1 0 -1 < \ output from REPRESENT
<ok> 8551 15 dump \ REPRESENT buffer contents
7 8 9 A B C D E F 0 1 2 3 4 5
03BA:2167 31 30 30 30 30 30 30 30 30 30 30 30 30 30 30 100000000000000
<ok> go ok 9373 2 < \ result from (f.)
0.4e 0 (f.) \ round r to 0 decimal places, output as a string
1 set-precision ok
0e 0e f/ 0 (fs.) \ round r to 0 decimal places, output as a string
<BREAK> stack= 8551 1 < \ input to REPRESENT
<ok> go
<BREAK> stack= 0 -1 0 < \ output from REPRESENT
<ok> 8551 15 dump \ REPRESENT buffer contents
7 8 9 A B C D E F 0 1 2 3 4 5
03BA:2167 2D 4E 41 4E 20 20 20 20 20 20 20 20 20 20 20 -NAN
<ok> go ok 9371 4 < \ result from (f.)
As can be seen, at least 15 digits/characters is always returned.
'u' merely sets the rounding to be applied in the case of numerics.
In the case of a NAN, the result is a blank-padded graphic string.
On 9/21/26 12:41 AM, dxf wrote:
On 21/09/2026 1:43 pm, Krishna Myneni wrote:
On 9/20/26 10:02 PM, dxf wrote:
On 21/09/2026 2:10 am, Krishna Myneni wrote:
...I think maybe what you are asking for is a different REPRESENT for small systems which can't afford the cost of complying with the current standard. That's a reasonable request.
AFAICS ANS neither required - nor excluded - a 750 digit REPRESENT.
What REPRESENT does exclude - if one accepts the interpretation of many >>>> an implementer - is the ability to handle the following scenarios.
-a-a-a 0.9e 0 (f.) type 1. ok
-a-a-a 0.4e 0 (f.) type 0. ok
-a-a-a 1 set-precision-a ok
-a-a-a 0e 0e f/ (fs.) type -NAN ok
For my part, I considered it enough of a problem to do something about it. >>>>
Show me what is being passed to REPRESENT for the above examples. I don't disagree there may be a problem. I can't see it from your examples since it doesn't show how REPRESENT is being used.
Here are the three cases.-a Breakpoints were inserted immediately before/after
REPRESENT.-a Comments added.
-a-a 0.9e 0 (f.)-a \ round r to 0 decimal places, output as a string
-a-a <BREAK>-a stack=-a 8551 0 <-a \ input to REPRESENT
This couldn't be the entire set of args to REPRESENT.-a 8551 appears to be the address of the buffer, but where is the floating point argument? I thought you were using an integrated data/fp stack. Do you now use a separate fp stack?
-a-a <ok> go
-a-a <BREAK>-a stack=-a 1 0 -1 <-a \ output from REPRESENT
Conversion succeeded, sign is zero, and decimal exponent is 1.
-a-a <ok> 8551 15 dump-a \ REPRESENT buffer contents
-a-a-a-a-a-a-a-a-a-a-a-a-a 7-a 8-a 9-a A-a B-a C-a D-a E-a F-a 0-a 1-a 2-a 3-a 4-a 5
-a-a 03BA:2167 31 30 30 30 30 30 30 30 30 30 30 30 30 30 30 100000000000000 >>
The buffer contents are meaningless since you asked for zero digits of the significand. If this needs to be spelled out in the standard it can be, but it is an obvious thing to deduce.
Zero digits refers to the number of significant digits, *not to the number of decimal places*! Nothing should have been written to the buffer at all.
-a-a <ok> go-a ok-a 9373 2 <-a \ result from (f.)
Whatever string is returned from (f.) is meaningless, and the sound behavior for it would be to check if the requested significant digits are zero (not decimal places), and if so return a zero length string.
-a-a 0.4e 0 (f.)-a \ round r to 0 decimal places, output as a string
Your argument to REPRESENT should be 1 if you want one significant digit, not zero.
0.4e0 PAD 1 REPRESENT .S
-a-a-a-a-a-a-a -1
-a-a-a-a-a-a-a 0
-a-a-a-a-a-a-a 0
The conversion succeeds, the sign is positive, and the decimal exponent is 0 with the implied decimal point at the left of the first digit.
PAD 1 TYPE
-a4 ok
The return parameters from REPRESENT tell you that the output in fixed form will be 0.4. Everything returned is consistent with the standard but you may be thinking in decimal places as the argument for REPRESENT rather than significant digits.
Your conversion failed, as it should have. The buffer is meaningless per the standard, which specifies no method of indicating an error. This does not prevent you from implementing one e.g. in kForth, REPRESENT returns 9999 for an IEEE +/-NAN or +/-INF.
-a-a 1 set-precision-a ok
-a-a 0e 0e f/ 0 (fs.)-a \ round r to 0 decimal places, output as a string
-a-a <BREAK>-a stack=-a 8551 1 <-a \ input to REPRESENT
-a-a <ok> go
-a-a <BREAK>-a stack=-a 0 -1 0 <-a \ output from REPRESENT
0e 0e F/ PAD 1 REPRESENT .S
-a-a-a-a-a-a-a 0
-a-a-a-a-a-a-a -1
-a-a-a-a-a-a-a 9999
Special values such as IEEE INF and NAN are not addressed in the standard floating point word set because there is no presumption of them. When a IEEE floating point word set is adopted, REPRESENT can be specified to return an error such as the one above, or another means of checking for an error such as an exception flag can be provided. The current REPRESENT standard says,
"When flag2 is false, n and flag1 are implementation defined, as are the contents of c-addr. Under these circumstances, the string at c-addr shall consist of graphic characters."
The contents of the buffer are implementation-dependent when the conversion fails. For an IEEE floating point word set, the contents will have to be spelled out, but until then no more can be said.
-a-a <ok> 8551 15 dump-a \ REPRESENT buffer contentsThat's consistent with the current standard, which says it is implementation defined.
-a-a-a-a-a-a-a-a-a-a-a-a-a 7-a 8-a 9-a A-a B-a C-a D-a E-a F-a 0-a 1-a 2-a 3-a 4-a 5
-a-a 03BA:2167 2D 4E 41 4E 20 20 20 20 20 20 20 20 20 20 20 -NAN
-a-a <ok> go-a ok-a 9371 4 <-a \ result from (f.)
As can be seen, at least 15 digits/characters is always returned.
'u' merely sets the rounding to be applied in the case of numerics.
In the case of a NAN, the result is a blank-padded graphic string.
On 22/09/2026 1:16 pm, Krishna Myneni wrote:
On 9/21/26 12:41 AM, dxf wrote:
On 21/09/2026 1:43 pm, Krishna Myneni wrote:
On 9/20/26 10:02 PM, dxf wrote:
On 21/09/2026 2:10 am, Krishna Myneni wrote:
...I think maybe what you are asking for is a different REPRESENT for small systems which can't afford the cost of complying with the current standard. That's a reasonable request.
AFAICS ANS neither required - nor excluded - a 750 digit REPRESENT.
What REPRESENT does exclude - if one accepts the interpretation of many >>>>> an implementer - is the ability to handle the following scenarios.
-a-a-a 0.9e 0 (f.) type 1. ok
-a-a-a 0.4e 0 (f.) type 0. ok
-a-a-a 1 set-precision-a ok
-a-a-a 0e 0e f/ (fs.) type -NAN ok
For my part, I considered it enough of a problem to do something about it.
Show me what is being passed to REPRESENT for the above examples. I don't disagree there may be a problem. I can't see it from your examples since it doesn't show how REPRESENT is being used.
Here are the three cases.-a Breakpoints were inserted immediately before/after
REPRESENT.-a Comments added.
-a-a 0.9e 0 (f.)-a \ round r to 0 decimal places, output as a string
-a-a <BREAK>-a stack=-a 8551 0 <-a \ input to REPRESENT
This couldn't be the entire set of args to REPRESENT.-a 8551 appears to be the address of the buffer, but where is the floating point argument? I thought you were using an integrated data/fp stack. Do you now use a separate fp stack?
I have both. Separate stack is too expensive on the 8080. I'm not sure why r
wasn't shown but it's 0.9e i.e. the same value as the input to (F.)
-a-a <ok> go
-a-a <BREAK>-a stack=-a 1 0 -1 <-a \ output from REPRESENT
Conversion succeeded, sign is zero, and decimal exponent is 1.
-a-a <ok> 8551 15 dump-a \ REPRESENT buffer contents
-a-a-a-a-a-a-a-a-a-a-a-a-a 7-a 8-a 9-a A-a B-a C-a D-a E-a F-a 0-a 1-a 2-a 3-a 4-a 5
-a-a 03BA:2167 31 30 30 30 30 30 30 30 30 30 30 30 30 30 30 100000000000000
The buffer contents are meaningless since you asked for zero digits of the significand. If this needs to be spelled out in the standard it can be, but it is an obvious thing to deduce.
Zero digits refers to the number of significant digits, *not to the number of decimal places*! Nothing should have been written to the buffer at all.
-a-a <ok> go-a ok-a 9373 2 <-a \ result from (f.)
Whatever string is returned from (f.) is meaningless, and the sound behavior for it would be to check if the requested significant digits are zero (not decimal places), and if so return a zero length string.
It's not clear ANS specified a string of u chars be returned. It's not clear on
many points. What's clear is forth implementers have elected to provide something
that is plainly inferior to what other languages provide their users.
-a-a 0.4e 0 (f.)-a \ round r to 0 decimal places, output as a string
Your argument to REPRESENT should be 1 if you want one significant digit, not zero.
0.4e0 PAD 1 REPRESENT .S
-a-a-a-a-a-a-a -1
-a-a-a-a-a-a-a 0
-a-a-a-a-a-a-a 0
I need REPRESENT to round to 'zero decimal places' because the latter is *common
usage*. Having a float-to-string primitive that can't handle it is pointless.
Whether or not ANS thought that far makes no difference. I'm responsible for what
I implement. I believe dtoa() has an fcvt mode so it's there for the taking.
On 9/22/26 2:16 AM, dxf wrote:
On 22/09/2026 1:16 pm, Krishna Myneni wrote:
On 9/21/26 12:41 AM, dxf wrote:
On 21/09/2026 1:43 pm, Krishna Myneni wrote:
On 9/20/26 10:02 PM, dxf wrote:
On 21/09/2026 2:10 am, Krishna Myneni wrote:
...I think maybe what you are asking for is a different REPRESENT for small systems which can't afford the cost of complying with the current standard. That's a reasonable request.
AFAICS ANS neither required - nor excluded - a 750 digit REPRESENT. >>>>>>
What REPRESENT does exclude - if one accepts the interpretation of many >>>>>> an implementer - is the ability to handle the following scenarios. >>>>>>
-a-a-a-a 0.9e 0 (f.) type 1. ok
-a-a-a-a 0.4e 0 (f.) type 0. ok
-a-a-a-a 1 set-precision-a ok
-a-a-a-a 0e 0e f/ (fs.) type -NAN ok
For my part, I considered it enough of a problem to do something about it.
Show me what is being passed to REPRESENT for the above examples. I don't disagree there may be a problem. I can't see it from your examples since it doesn't show how REPRESENT is being used.
Here are the three cases.-a Breakpoints were inserted immediately before/after
REPRESENT.-a Comments added.
-a-a-a 0.9e 0 (f.)-a \ round r to 0 decimal places, output as a string >>>> -a-a-a <BREAK>-a stack=-a 8551 0 <-a \ input to REPRESENT
This couldn't be the entire set of args to REPRESENT.-a 8551 appears to be the address of the buffer, but where is the floating point argument? I thought you were using an integrated data/fp stack. Do you now use a separate fp stack?
I have both.-a Separate stack is too expensive on the 8080.-a I'm not sure why r
wasn't shown but it's 0.9e i.e. the same value as the input to (F.)
-a-a-a <ok> go
-a-a-a <BREAK>-a stack=-a 1 0 -1 <-a \ output from REPRESENT
Conversion succeeded, sign is zero, and decimal exponent is 1.
-a-a-a <ok> 8551 15 dump-a \ REPRESENT buffer contents
-a-a-a-a-a-a-a-a-a-a-a-a-a-a 7-a 8-a 9-a A-a B-a C-a D-a E-a F-a 0-a 1-a 2-a 3-a 4-a 5
-a-a-a 03BA:2167 31 30 30 30 30 30 30 30 30 30 30 30 30 30 30 100000000000000
The buffer contents are meaningless since you asked for zero digits of the significand. If this needs to be spelled out in the standard it can be, but it is an obvious thing to deduce.
Zero digits refers to the number of significant digits, *not to the number of decimal places*! Nothing should have been written to the buffer at all.
-a-a-a <ok> go-a ok-a 9373 2 <-a \ result from (f.)
Whatever string is returned from (f.) is meaningless, and the sound behavior for it would be to check if the requested significant digits are zero (not decimal places), and if so return a zero length string.
It's not clear ANS specified a string of u chars be returned.-a It's not clear on
many points.-a What's clear is forth implementers have elected to provide something
that is plainly inferior to what other languages provide their users.
I don't know how the standard for REPRESENT could be more clear on this point:
"The character string shall consist of the u most significant digits
of the significand..."
-a-a-a 0.4e 0 (f.)-a \ round r to 0 decimal places, output as a string
Your argument to REPRESENT should be 1 if you want one significant digit, not zero.
0.4e0 PAD 1 REPRESENT .S
-a-a-a-a-a-a-a-a -1
-a-a-a-a-a-a-a-a 0
-a-a-a-a-a-a-a-a 0
I need REPRESENT to round to 'zero decimal places' because the latter is *common
usage*.-a Having a float-to-string primitive that can't handle it is pointless.
Whether or not ANS thought that far makes no difference.-a I'm responsible for what
I implement.-a I believe dtoa() has an fcvt mode so it's there for the taking.
The are no a priori decimal places until the rounding to u significant digits occurs. REPRESENT takes the number of significant digits u as the input and tells you the exponent. REPRESENT is not your problem. How you are interpreting the results is the issue. You can write the formatted string output word to behave as you desire once you understand how to use REPRESENT.
On 22/09/2026 10:34 pm, Krishna Myneni wrote:...
I don't understand how to use REPRESENT. Could you please show me how you would implement the following?
(F.) ( r n -- addr len ) ( F: r -- ) ( n -- addr len )
Convert real number r to string c-addr u in the HOLD buffer in fixed-point
notation with n places to the right of the decimal point. n is greater
than, or equal to, zero.
On 9/22/26 9:16 AM, dxf wrote:
On 22/09/2026 10:34 pm, Krishna Myneni wrote:...
I don't understand how to use REPRESENT.-a Could you please show me how you >> would implement the following?
-a-a (F.)-a ( r n -- addr len ) ( F: r -- ) ( n -- addr len )
-a-a Convert real number r to string c-addr u in the HOLD buffer in fixed-point
-a-a notation with n places to the right of the decimal point.-a n is greater
-a-a than, or equal to, zero.
Yes, but it will be a few days. This is a good exercise and I hope it will show that REPRESENT is the primitive for binary floating point to decimal string conversions, in whatever format you want. I already demonstrated (FS.) but fixed point format might need a little extra logic. REPRESENT provides the decimal characters so there is no need to use the pictured numeric output words.
My fixed point output word F.RD in the kForth strings library (strings.4th) needs to be updated to use REPRESENT.
On 23/09/2026 2:44 am, Krishna Myneni wrote:
On 9/22/26 9:16 AM, dxf wrote:
On 22/09/2026 10:34 pm, Krishna Myneni wrote:...
I don't understand how to use REPRESENT.-a Could you please show me how you >>> would implement the following?
-a-a (F.)-a ( r n -- addr len ) ( F: r -- ) ( n -- addr len )
-a-a Convert real number r to string c-addr u in the HOLD buffer in fixed-point
-a-a notation with n places to the right of the decimal point.-a n is greater
-a-a than, or equal to, zero.
Yes, but it will be a few days. This is a good exercise and I hope it will show that REPRESENT is the primitive for binary floating point to decimal string conversions, in whatever format you want. I already demonstrated (FS.) but fixed point format might need a little extra logic. REPRESENT provides the decimal characters so there is no need to use the pictured numeric output words.
My fixed point output word F.RD in the kForth strings library (strings.4th) needs to be updated to use REPRESENT.
In the meantime here is a fun fact. Almost all ANS-compliant REPRESENT implementations currently in use already do the conversion that you
contend isn't necessary.
Below is Swiftforth's REPRESENT reduced to the basic conversion operation. Forth Inc copyright is acknowledged. Material presented here is claimed under 'fair use for educational purposes' copyright provisions.
: REPRESENT ( c-addr u -- ... ) ( r -- )
FABS
MAX-FBUFFER MIN DUP #EXP - 1- >10** FROUND
F>D <# #S #>
;
0.9e pad 0 represent cr type
1 ok
0.4e pad 0 represent cr type
0 ok
On 23/09/2026 2:44 am, Krishna Myneni wrote:...
In the meantime here is a fun fact. Almost all ANS-compliant REPRESENT implementations currently in use already do the conversion that you
contend isn't necessary.
Below is Swiftforth's REPRESENT reduced to the basic conversion operation. Forth Inc copyright is acknowledged. Material presented here is claimed under 'fair use for educational purposes' copyright provisions.
: REPRESENT ( c-addr u -- ... ) ( r -- )
FABS
MAX-FBUFFER MIN DUP #EXP - 1- >10** FROUND
F>D <# #S #>
;
On 9/22/26 8:55 PM, dxf wrote:
On 23/09/2026 2:44 am, Krishna Myneni wrote:...
In the meantime here is a fun fact.-a Almost all ANS-compliant REPRESENT
implementations currently in use already do the conversion that you
contend isn't necessary.
You didn't read my earlier reply from yesterday carefully. I didn't say REPRESENT does not need the numeric pictured output words (if it were implemented in Forth). I said that the higher level string formatting words using REPRESENT do not need them.
Right now, I'm not trying to implement a "proper" REPRESENT in Forth. It appears that no one in the community has been interested in doing, but it's something that should be done.
Below is Swiftforth's REPRESENT reduced to the basic conversion operation. >> Forth Inc copyright is acknowledged.-a Material presented here is claimedWhat's the definition of #EXP?
under 'fair use for educational purposes' copyright provisions.
: REPRESENT ( c-addr u -- ... ) ( r -- )
-a-a-a FABS
-a-a-a MAX-FBUFFER MIN-a DUP #EXP - 1- >10** FROUND
-a-a-a F>D <# #S #>
;
Isn't that the source of your grief with writing properly rounded formatting words?
( F: r -- r ) ( -- exp )
FDUP F0= IF 0 EXIT THEN
FDUP FABS FLOG FLOOR F>S
float float array (log2>log10) latest f! does> f@ f* ;
On 24-09-2026 03:34, dxf wrote:
-a-a ( F: r -- r ) ( -- exp )
-a-a FDUP F0= IF-a 0-a EXIT-a THEN
-a-a FDUP FABS FLOG FLOOR F>S
I think this one is faster - if you have FREXP, that is.
s" 0.3010299956639811952137388947244930267681898814621085413104274611" s>float float array (log2>log10) latest f! does> f@ f* ;
: #exp
-a fdup f0= if 0 ;then frexp 1- >r 1 s>f 2 s>f f/ f- f2*
-a r> s>f f+ (log2>log10) floor f>s
;
On 25/09/2026 1:51 am, Hans Bezemer wrote:
On 24-09-2026 03:34, dxf wrote:
-a-a ( F: r -- r ) ( -- exp )
-a-a FDUP F0= IF-a 0-a EXIT-a THEN
-a-a FDUP FABS FLOG FLOOR F>S
I think this one is faster - if you have FREXP, that is.
s" 0.3010299956639811952137388947244930267681898814621085413104274611"
float float array (log2>log10) latest f! does> f@ f* ;
: #exp
-a fdup f0= if 0 ;then frexp 1- >r 1 s>f 2 s>f f/ f- f2*
-a r> s>f f+ (log2>log10) floor f>s
;
With only 64K, the bean counter in me is always nagging about bytes spent.
At the moment the s/w fp doesn't even use FLOG. I can't remember if there was a reason and sometimes it's better to let sleeping dogs lie.
On 25/09/2026 1:51 am, Hans Bezemer wrote:
On 24-09-2026 03:34, dxf wrote:
-a-a ( F: r -- r ) ( -- exp )
-a-a FDUP F0= IF-a 0-a EXIT-a THEN
-a-a FDUP FABS FLOG FLOOR F>S
I think this one is faster - if you have FREXP, that is.
s" 0.3010299956639811952137388947244930267681898814621085413104274611"
float float array (log2>log10) latest f! does> f@ f* ;
: #exp
-a fdup f0= if 0 ;then frexp 1- >r 1 s>f 2 s>f f/ f- f2*
-a r> s>f f+ (log2>log10) floor f>s
;
With only 64K, the bean counter in me is always nagging about bytes spent.
At the moment the s/w fp doesn't even use FLOG. I can't remember if there was a reason and sometimes it's better to let sleeping dogs lie.
base !
base !
On 25/09/2026 1:51 am, Hans Bezemer wrote:
On 24-09-2026 03:34, dxf wrote:
-a-a ( F: r -- r ) ( -- exp )
-a-a FDUP F0= IF-a 0-a EXIT-a THEN
-a-a FDUP FABS FLOG FLOOR F>S
I think this one is faster - if you have FREXP, that is.
s" 0.3010299956639811952137388947244930267681898814621085413104274611"
float float array (log2>log10) latest f! does> f@ f* ;
: #exp
-a fdup f0= if 0 ;then frexp 1- >r 1 s>f 2 s>f f/ f- f2*
-a r> s>f f+ (log2>log10) floor f>s
;
With only 64K, the bean counter in me is always nagging about bytes spent.
At the moment the s/w fp doesn't even use FLOG. I can't remember if there was a reason and sometimes it's better to let sleeping dogs lie.
On 24-09-2026 19:18, dxf wrote:
On 25/09/2026 1:51 am, Hans Bezemer wrote:
On 24-09-2026 03:34, dxf wrote:
-a-a-a ( F: r -- r ) ( -- exp )
-a-a-a FDUP F0= IF-a 0-a EXIT-a THEN
-a-a-a FDUP FABS FLOG FLOOR F>S
I think this one is faster - if you have FREXP, that is.
s" 0.3010299956639811952137388947244930267681898814621085413104274611"
float float array (log2>log10) latest f! does> f@ f* ;
: #exp
-a-a fdup f0= if 0 ;then frexp 1- >r 1 s>f 2 s>f f/ f- f2*
-a-a r> s>f f+ (log2>log10) floor f>s
;
With only 64K, the bean counter in me is always nagging about bytes spent. >> At the moment the s/w fp doesn't even use FLOG.-a I can't remember if there >> was a reason and sometimes it's better to let sleeping dogs lie.
It seems to me like DX-Forth doesn't support IEEE singles. If it were, this might be a solution:
...
On 25/09/2026 1:51 am, Hans Bezemer wrote:
On 24-09-2026 03:34, dxf wrote:
-a-a ( F: r -- r ) ( -- exp )
-a-a FDUP F0= IF-a 0-a EXIT-a THEN
-a-a FDUP FABS FLOG FLOOR F>S
I think this one is faster - if you have FREXP, that is.
s" 0.3010299956639811952137388947244930267681898814621085413104274611"
float float array (log2>log10) latest f! does> f@ f* ;
: #exp
-a fdup f0= if 0 ;then frexp 1- >r 1 s>f 2 s>f f/ f- f2*
-a r> s>f f+ (log2>log10) floor f>s
;
With only 64K, the bean counter in me is always nagging about bytes spent.
At the moment the s/w fp doesn't even use FLOG. I can't remember if there was a reason and sometimes it's better to let sleeping dogs lie.
base !
On 25/09/2026 5:09 pm, Hans Bezemer wrote:
On 24-09-2026 19:18, dxf wrote:
On 25/09/2026 1:51 am, Hans Bezemer wrote:
On 24-09-2026 03:34, dxf wrote:
-a-a-a ( F: r -- r ) ( -- exp )
-a-a-a FDUP F0= IF-a 0-a EXIT-a THEN
-a-a-a FDUP FABS FLOG FLOOR F>S
I think this one is faster - if you have FREXP, that is.
s" 0.3010299956639811952137388947244930267681898814621085413104274611" >>>> s>float float array (log2>log10) latest f! does> f@ f* ;
: #exp
-a-a fdup f0= if 0 ;then frexp 1- >r 1 s>f 2 s>f f/ f- f2*
-a-a r> s>f f+ (log2>log10) floor f>s
;
With only 64K, the bean counter in me is always nagging about bytes spent. >>> At the moment the s/w fp doesn't even use FLOG.-a I can't remember if there >>> was a reason and sometimes it's better to let sleeping dogs lie.
It seems to me like DX-Forth doesn't support IEEE singles. If it were, this might be a solution:
...
It does (see F87S.SCR) and FLOG there suffices. Just trying out your FREXP is complicated since ints are 16-bit and the fp is common stack.
...
\ untested
: frexp-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a ( f1 -- f2 n)
-a fdup f0= if fdrop 0 s>f 0 exit then
-a (ieee32) f! (ieee32) 2@ 2dup 17 drshift 0ff. dand d>s
-a 0ff = if drop 2drop (ieee32) f@ 0 exit then
-a 07e - >r 0807fffff. dand 03f000000. dor (ieee32) tuck ! f@ r>
;
Does this help a bit? UNTESTED, which should be expected.
It does (see F87S.SCR) and FLOG there suffices. Just trying out your FREXP is complicated since ints are 16-bit and the fp is common stack.
(tiny typo corrected). We were close! But you won! :-)It does (see F87S.SCR) and FLOG there suffices.-a Just trying out your
FREXP
is complicated since ints are 16-bit and the fp is common stack.
It was quite a battle, but I succeeded:
On 25/09/2026 10:02 pm, Hans Bezemer wrote:
...
\ untested
: frexp-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a ( f1 -- f2 n)
-a fdup f0= if fdrop 0 s>f 0 exit then
-a (ieee32) f! (ieee32) 2@ 2dup 17 drshift 0ff. dand d>s
-a 0ff = if drop 2drop (ieee32) f@ 0 exit then
-a 07e - >r 0807fffff. dand 03f000000. dor (ieee32) tuck ! f@ r>
;
Does this help a bit? UNTESTED, which should be expected.
AFAICT it should be at least this:
: frexp ( f1 -- f2 n)
fdup f0= if fdrop 0 s>f 0 exit then (ieee32) f!
(ieee32) 2@ swap 2dup $17 drshift $0ff. dand d>s
dup $0ff = if drop 2drop (ieee32) f@ 0 exit then
$07e - >r $0807fffff. dand $03f000000. dor
swap (ieee32) 2! (ieee32) f@ r>
;
and that seems to work.
On 25-09-2026 16:20, dxf wrote:
On 25/09/2026 10:02 pm, Hans Bezemer wrote:
...
\ untested
: frexp-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a ( f1 -- f2 n)
-a-a fdup f0= if fdrop 0 s>f 0 exit then
-a-a (ieee32) f! (ieee32) 2@ 2dup 17 drshift 0ff. dand d>s
-a-a 0ff = if drop 2drop (ieee32) f@ 0 exit then
-a-a 07e - >r 0807fffff. dand 03f000000. dor (ieee32) tuck ! f@ r>
;
Does this help a bit? UNTESTED, which should be expected.
AFAICT it should be at least this:
: frexp-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a ( f1 -- f2 n)
-a-a fdup f0= if fdrop 0 s>f 0 exit then-a (ieee32) f!
-a-a (ieee32) 2@ swap-a 2dup $17 drshift-a $0ff. dand d>s
-a-a dup $0ff = if drop 2drop (ieee32) f@ 0 exit then
-a-a $07e - >r-a $0807fffff. dand $03f000000. dor
-a-a swap (ieee32) 2!-a (ieee32) f@ r>
;
and that seems to work.
BTW, this tiny addition (after: dup $0ff) should be able to do subnormal numbers (UNTESTED):
0 256 2constant 2^24
dup 0= if drop 2drop (ieee32) f@ 2^24 d>f f* recurse 18 - exit then
I recently updated the I/O routines on my x87 packs only to discover I
could no longer enter and get subnormals. I've not looked into why and
for the time being decided to live with it. But we'll see.
On 9/22/26 9:16 AM, dxf wrote:
On 22/09/2026 10:34 pm, Krishna Myneni wrote:...
I don't understand how to use REPRESENT.-a Could you please show me how
you
would implement the following?
-a-a (F.)-a ( r n -- addr len ) ( F: r -- ) ( n -- addr len )
-a-a Convert real number r to string c-addr u in the HOLD buffer in
fixed-point
-a-a notation with n places to the right of the decimal point.-a n is
greater
-a-a than, or equal to, zero.
Yes, but it will be a few days. This is a good exercise and I hope it
will show that REPRESENT is the primitive for binary floating point to decimal string conversions, in whatever format you want. I already demonstrated (FS.) but fixed point format might need a little extra
logic. REPRESENT provides the decimal characters so there is no need to
use the pictured numeric output words.
My fixed point output word F.RD in the kForth strings library
(strings.4th) needs to be updated to use REPRESENT.
On 9/22/26 11:44 AM, Krishna Myneni wrote:
On 9/22/26 9:16 AM, dxf wrote:
On 22/09/2026 10:34 pm, Krishna Myneni wrote:...
I don't understand how to use REPRESENT.-a Could you please show me how you >>> would implement the following?
-a-a (F.)-a ( r n -- addr len ) ( F: r -- ) ( n -- addr len )
-a-a Convert real number r to string c-addr u in the HOLD buffer in fixed-point
-a-a notation with n places to the right of the decimal point.-a n is greater
-a-a than, or equal to, zero.
Yes, but it will be a few days. This is a good exercise and I hope it will show that REPRESENT is the primitive for binary floating point to decimal string conversions, in whatever format you want. I already demonstrated (FS.) but fixed point format might need a little extra logic. REPRESENT provides the decimal characters so there is no need to use the pictured numeric output words.
My fixed point output word F.RD in the kForth strings library (strings.4th) needs to be updated to use REPRESENT.
Sneak preview of definition F.N which prints a double precision floating point number, *rounded correctly* to n decimal places (not n significant digits) and implemented using a high quality REPRESENT:
...
-0.6e 25 f.n
-0.5999999999999999777955395 ok
-0.6e 23 f.n
-0.59999999999999997779554 ok-a \ rounding to 23 dp
There's more work to be done before it is generally usable, but it demonstrates that one can write a fixed point formatting word which rounds correctly to n decimal places using REPRESENT (which takes number of significant digits as an argument). The logic is more complex than for scientific notation output which is specified by PRECISION.
On 26/09/2026 10:09 pm, Krishna Myneni wrote:
On 9/22/26 11:44 AM, Krishna Myneni wrote:
On 9/22/26 9:16 AM, dxf wrote:
On 22/09/2026 10:34 pm, Krishna Myneni wrote:...
I don't understand how to use REPRESENT.-a Could you please show me how you
would implement the following?
-a-a (F.)-a ( r n -- addr len ) ( F: r -- ) ( n -- addr len )
-a-a Convert real number r to string c-addr u in the HOLD buffer in fixed-point
-a-a notation with n places to the right of the decimal point.-a n is greater
-a-a than, or equal to, zero.
Yes, but it will be a few days. This is a good exercise and I hope it will show that REPRESENT is the primitive for binary floating point to decimal string conversions, in whatever format you want. I already demonstrated (FS.) but fixed point format might need a little extra logic. REPRESENT provides the decimal characters so there is no need to use the pictured numeric output words.
My fixed point output word F.RD in the kForth strings library (strings.4th) needs to be updated to use REPRESENT.
Sneak preview of definition F.N which prints a double precision floating point number, *rounded correctly* to n decimal places (not n significant digits) and implemented using a high quality REPRESENT:
...
-0.6e 25 f.n
-0.5999999999999999777955395 ok
-0.6e 23 f.n
-0.59999999999999997779554 ok-a \ rounding to 23 dp
Is that what printf in GCC gives these days? Because as a user I'm not
sure I'd like it.
REPRESENT with 0 argument for the number of significant digits.There's more work to be done before it is generally usable, but it demonstrates that one can write a fixed point formatting word which rounds correctly to n decimal places using REPRESENT (which takes number of significant digits as an argument). The logic is more complex than for scientific notation output which is specified by PRECISION.
What do you get for these?
0.9e 0 f.n
0.4e 0 f.n
I'm still working on the logic for n = 0. It will not involve calling
On 9/26/26 10:36 AM, dxf wrote:
On 26/09/2026 10:09 pm, Krishna Myneni wrote:These are the actual digits of the binary representation of the decimal input -0.6e, rounded correctly to the number of decimal places passed to f.n. GCC printf is not being used by the Forth code.
On 9/22/26 11:44 AM, Krishna Myneni wrote:
On 9/22/26 9:16 AM, dxf wrote:
On 22/09/2026 10:34 pm, Krishna Myneni wrote:...
I don't understand how to use REPRESENT.-a Could you please show me >>>>> how you
would implement the following?
-a-a-a (F.)-a ( r n -- addr len ) ( F: r -- ) ( n -- addr len )
-a-a-a Convert real number r to string c-addr u in the HOLD buffer in >>>>> fixed-point
-a-a-a notation with n places to the right of the decimal point.-a n is >>>>> greater
-a-a-a than, or equal to, zero.
Yes, but it will be a few days. This is a good exercise and I hope
it will show that REPRESENT is the primitive for binary floating
point to decimal string conversions, in whatever format you want. I
already demonstrated (FS.) but fixed point format might need a
little extra logic. REPRESENT provides the decimal characters so
there is no need to use the pictured numeric output words.
My fixed point output word F.RD in the kForth strings library
(strings.4th) needs to be updated to use REPRESENT.
Sneak preview of definition F.N which prints a double precision
floating point number, *rounded correctly* to n decimal places (not n
significant digits) and implemented using a high quality REPRESENT:
...
-0.6e 25 f.n
-0.5999999999999999777955395 ok
-0.6e 23 f.n
-0.59999999999999997779554 ok-a \ rounding to 23 dp
Is that what printf in GCC gives these days?-a Because as a user I'm not
sure I'd like it.
There's more work to be done before it is generally usable, but it
demonstrates that one can write a fixed point formatting word which
rounds correctly to n decimal places using REPRESENT (which takes
number of significant digits as an argument). The logic is more
complex than for scientific notation output which is specified by
PRECISION.
What do you get for these?
0.9e 0 f.n
0.4e 0 f.n
I'm still working on the logic for n = 0. It will not involve calling REPRESENT with 0 argument for the number of significant digits.
On 9/26/26 10:36 AM, dxf wrote:
On 26/09/2026 10:09 pm, Krishna Myneni wrote:These are the actual digits of the binary representation of the decimal input -0.6e, rounded correctly to the number of decimal places passed to f.n. GCC printf is not being used by the Forth code.
On 9/22/26 11:44 AM, Krishna Myneni wrote:
On 9/22/26 9:16 AM, dxf wrote:
On 22/09/2026 10:34 pm, Krishna Myneni wrote:...
I don't understand how to use REPRESENT.-a Could you please show me how you
would implement the following?
-a-a-a (F.)-a ( r n -- addr len ) ( F: r -- ) ( n -- addr len )
-a-a-a Convert real number r to string c-addr u in the HOLD buffer in fixed-point
-a-a-a notation with n places to the right of the decimal point.-a n is greater
-a-a-a than, or equal to, zero.
Yes, but it will be a few days. This is a good exercise and I hope it will show that REPRESENT is the primitive for binary floating point to decimal string conversions, in whatever format you want. I already demonstrated (FS.) but fixed point format might need a little extra logic. REPRESENT provides the decimal characters so there is no need to use the pictured numeric output words.
My fixed point output word F.RD in the kForth strings library (strings.4th) needs to be updated to use REPRESENT.
Sneak preview of definition F.N which prints a double precision floating point number, *rounded correctly* to n decimal places (not n significant digits) and implemented using a high quality REPRESENT:
...
-0.6e 25 f.n
-0.5999999999999999777955395 ok
-0.6e 23 f.n
-0.59999999999999997779554 ok-a \ rounding to 23 dp
Is that what printf in GCC gives these days?-a Because as a user I'm not
sure I'd like it.
REPRESENT with 0 argument for the number of significant digits.There's more work to be done before it is generally usable, but it demonstrates that one can write a fixed point formatting word which rounds correctly to n decimal places using REPRESENT (which takes number of significant digits as an argument). The logic is more complex than for scientific notation output which is specified by PRECISION.
What do you get for these?
0.9e 0 f.n
0.4e 0 f.n
I'm still working on the logic for n = 0. It will not involve calling
On 27/09/2026 2:25 am, Krishna Myneni wrote:...
These are the actual digits of the binary representation of the decimal input -0.6e, rounded correctly to the number of decimal places passed to f.n. GCC printf is not being used by the Forth code.-0.6e 23 f.n
-0.59999999999999997779554 ok-a \ rounding to 23 dp
Is that what printf in GCC gives these days?-a Because as a user I'm not >>> sure I'd like it.
If someone does know what GCC printf displays, I'd be interested.
On 27/09/2026 2:25 am, Krishna Myneni wrote:
I'm still working on the logic for n = 0. It will not involve calling
REPRESENT with 0 argument for the number of significant digits.
Logical would be letting REPRESENT do what it can.
On 9/26/26 3:17 PM, dxf wrote:
On 27/09/2026 2:25 am, Krishna Myneni wrote:...
These are the actual digits of the binary representation of the decimal input -0.6e, rounded correctly to the number of decimal places passed to f.n. GCC printf is not being used by the Forth code.-0.6e 23 f.n
-0.59999999999999997779554 ok-a \ rounding to 23 dp
Is that what printf in GCC gives these days?-a Because as a user I'm not >>>> sure I'd like it.
If someone does know what GCC printf displays, I'd be interested.
-a
===
/*
Print the double 0.6 to 25 decimal places
*/
#include <stdio.h>
#include <math.h>
int main(void)
{
-a double x = 0.6;
-a printf("\nx: %.25g\n", x);
-a return 0;
}
$ gcc -o print_0.6 print_0.6.c
$ ./print_0.6
x: 0.5999999999999999777955395
===
I don't understand your disbelief that 0.6 cannot be represented exactly in IEEE 754 double precision. Do you want the computer to lie to you? You can always ask for fewer decimal places, like 16 or less, if you don't want to see the ugliness of floating point.
On 27/09/2026 7:24 am, Krishna Myneni wrote:
On 9/26/26 3:17 PM, dxf wrote:
On 27/09/2026 2:25 am, Krishna Myneni wrote:...
These are the actual digits of the binary representation of the decimal input -0.6e, rounded correctly to the number of decimal places passed to f.n. GCC printf is not being used by the Forth code.-0.6e 23 f.n
-0.59999999999999997779554 ok-a \ rounding to 23 dp
Is that what printf in GCC gives these days?-a Because as a user I'm not >>>>> sure I'd like it.
If someone does know what GCC printf displays, I'd be interested.
===
/*
Print the double 0.6 to 25 decimal places
*/
#include <stdio.h>
#include <math.h>
int main(void)
{
-a double x = 0.6;
-a printf("\nx: %.25g\n", x);
-a return 0;
}
$ gcc -o print_0.6 print_0.6.c
$ ./print_0.6
x: 0.5999999999999999777955395
===
I don't understand your disbelief that 0.6 cannot be represented exactly in IEEE 754 double precision. Do you want the computer to lie to you? You can always ask for fewer decimal places, like 16 or less, if you don't want to see the ugliness of floating point.
The ugliness of fp lies in the math - the 15 or 16 digit max result that comes from using double precision. Unless IEEE is perverse, wants to add
to users burdens, I very much doubt it required what GCC has done. FWIW
I have the same opinion about ANS. I reject interpretations of REPRESENT that make ANS and its users look perverse and stupid. But if that's what they want, it's ok.
Asking fewer 'decimal places' doesn't solve GCC's thought bubble. What's needed is a 'significant digits' control.
AFAIK, IEEE 754 only states how many significant digits should be
accurately output for a round trip conversion to binary format (17
digits), and does not otherwise specify a maximum number of digits to be accurately output on any system for binary to decimal string conversion.
My understanding is that if your system outputs 17 significant decimal digits (not decimal places) accurately and converts strings with decimal digits up to 17 significant digits accurately to within 1 ulp, it meets
the minimum requirements for double precision floating point. I will
check the draft version of IEEE 754 to see if there are any other requirements, but I don't know of any.
...
Therefore, if you do a conversion from a binary format to decimal characters, specifying the number of significant digits, it is incompatible with converting back to the original decimal format. However, if you use an internal IEEE decimal floating point format, it is possible to preserve the digits from the original string.
Forth's REPRESENT requires significant digits as an input since it is converting binary format to decimal digits. You can use it to implement a conversion with a specific number of decimal places, but you are not guaranteed to obtain the same digits as in the original decimal string.
Incidentally, David Gay, the author of the C code (dtoa.c), which can be used to implement REPRESENT, was one of the members of the IEEE 754 standardization committee in 2019.
On 28/09/2026 3:37 am, Krishna Myneni wrote:
...
Therefore, if you do a conversion from a binary format to decimal characters, specifying the number of significant digits, it is incompatible with converting back to the original decimal format. However, if you use an internal IEEE decimal floating point format, it is possible to preserve the digits from the original string.
Forth's REPRESENT requires significant digits as an input since it is converting binary format to decimal digits. You can use it to implement a conversion with a specific number of decimal places, but you are not guaranteed to obtain the same digits as in the original decimal string.
AFAIR ANS didn't specify binary, leaving it open to things such as BCD fp. ANS stated purpose was to "serve as a basis for the future evolution of the Forth language". Anything that arbitrarily excluded was avoided.
"REPRESENT requires significant digits as an input" is an interpretation I
do not accept because it limits what REPRESENT can plainly do - as I said. I've not said REPRESENT can't be used to return an IEEE storage slot number (all 750 digits) rounding it to some arbitrary figure the user has chosen
- if that's what he wants. Only that I have no use and would rather not
even see it.
On 9/27/26 10:52 PM, dxf wrote:
On 28/09/2026 3:37 am, Krishna Myneni wrote:
...
Therefore, if you do a conversion from a binary format to decimal characters, specifying the number of significant digits, it is incompatible with converting back to the original decimal format. However, if you use an internal IEEE decimal floating point format, it is possible to preserve the digits from the original string.
Forth's REPRESENT requires significant digits as an input since it is converting binary format to decimal digits. You can use it to implement a conversion with a specific number of decimal places, but you are not guaranteed to obtain the same digits as in the original decimal string.
AFAIR ANS didn't specify binary, leaving it open to things such as BCD fp. >> ANS stated purpose was to "serve as a basis for the future evolution of the >> Forth language".-a Anything that arbitrarily excluded was avoided.
Sure, you can implement decimal format fp numbers and be compatible with the Forth standard. Then you can output floating point numbers in exactly the same way as they were input by a string of decimal digits, down to the last digit. You would then have to implement decimal format floating point arithmetic in software.
"REPRESENT requires significant digits as an input" is an interpretation I >> do not accept because it limits what REPRESENT can plainly do - as I said. >> I've not said REPRESENT can't be used to return an IEEE storage slot number >> (all 750 digits) rounding it to some arbitrary figure the user has chosen
- if that's what he wants.-a Only that I have no use and would rather not
even see it.
Whether you accept it or not, that is the wording of the standard.
When you store the number in a different base than the base in which you input the number, a roundtrip conversion e.g. decimal to binary to decimal, which preserves the input to the least significant digit in the input is generally not possible, as noted in the IEEE 754 standard.
The problem is not with REPRESENT. Your issue is with not using an internal decimal format for floating point numbers. The IEEE 754 standard specifies 64-bit decimal formats as well.
On 28/09/2026 9:47 pm, Krishna Myneni wrote:
On 9/27/26 10:52 PM, dxf wrote:
On 28/09/2026 3:37 am, Krishna Myneni wrote:
...
Therefore, if you do a conversion from a binary format to decimal characters, specifying the number of significant digits, it is incompatible with converting back to the original decimal format. However, if you use an internal IEEE decimal floating point format, it is possible to preserve the digits from the original string.
Forth's REPRESENT requires significant digits as an input since it is converting binary format to decimal digits. You can use it to implement a conversion with a specific number of decimal places, but you are not guaranteed to obtain the same digits as in the original decimal string.
AFAIR ANS didn't specify binary, leaving it open to things such as BCD fp. >>> ANS stated purpose was to "serve as a basis for the future evolution of the >>> Forth language".-a Anything that arbitrarily excluded was avoided.
Sure, you can implement decimal format fp numbers and be compatible with the Forth standard. Then you can output floating point numbers in exactly the same way as they were input by a string of decimal digits, down to the last digit. You would then have to implement decimal format floating point arithmetic in software.
"REPRESENT requires significant digits as an input" is an interpretation I >>> do not accept because it limits what REPRESENT can plainly do - as I said. >>> I've not said REPRESENT can't be used to return an IEEE storage slot number >>> (all 750 digits) rounding it to some arbitrary figure the user has chosen >>> - if that's what he wants.-a Only that I have no use and would rather not >>> even see it.
Whether you accept it or not, that is the wording of the standard.
Sorry but no such wording exists.
When you store the number in a different base than the base in which you input the number, a roundtrip conversion e.g. decimal to binary to decimal, which preserves the input to the least significant digit in the input is generally not possible, as noted in the IEEE 754 standard.
The problem is not with REPRESENT. Your issue is with not using an internal decimal format for floating point numbers. The IEEE 754 standard specifies 64-bit decimal formats as well.
I have no issue. REPRESENT as I've implemented it fulfils my needs. Will you
be posting your fixed-point code routine? Gforth's f.rdp required a chunk of code be inserted to handle what its REPRESENT could not. I'm curious to see how much code you expend handling the situation.
Whether you accept it or not, that is the wording of the
standard. When you store the number in a different base than the base
in which you input the number, a roundtrip conversion e.g. decimal to
binary to decimal, which preserves the input to the least significant
digit in the input is generally not possible, as noted in the IEEE 754 standard.
The IEEE 754 standard specifies 64-bit decimal formats as well.
Krishna Myneni <krishna.myneni@ccreweb.org> writes:
Whether you accept it or not, that is the wording of the
standard. When you store the number in a different base than the base
in which you input the number, a roundtrip conversion e.g. decimal to
binary to decimal, which preserves the input to the least significant
digit in the input is generally not possible, as noted in the IEEE 754
standard.
I thought REPRESENT had to take an arbitrary IEEE 754 (binary) float and convert it to a decimal representation that could then be converted back
to the exact same binary float. That is, binary->decimal->binary. The
other way, decimal->binary->decimal, isn't always possible as you
mention, but it's not required.
The IEEE standard apparently requires binary->decimal->binary to work
when the decimal representation has at least 17 significant digits. I
don't see a good way to implement that off the top of my head, but it's apparently possible. Writing a small binary64 number like 2**-1000 as
an exact decimal number the dumb way can take an awful lot of digits.
The IEEE 754 standard specifies 64-bit decimal formats as well.
Unfortunately there's no cheap hardware that I know of that implements
this. It would be nice. I think it exists on some IBM mainframes and
POWER ISA chips. There's a spec for it in the RISC-V architecture docs
but IDK of any actual RISC-V chips that supply it. I wonder if it's
feasible to implement in a smallish FPGA.
Writing a small binary64 number like 2**-1000 as an exact decimalI don't follow what your saying here.
number the dumb way can take an awful lot of digits.
I bet there is hardware out there for decimal arithmetic
Krishna Myneni <krishna.myneni@ccreweb.org> writes:
Writing a small binary64 number like 2**-1000 as an exact decimalI don't follow what your saying here.
number the dumb way can take an awful lot of digits.
REPRESENT uses some kind of algorithm that, when the decimal precision
is >= 17, generates a decimal string that converts back to the same bit pattern. I just mean I don't see off the top of my head how that
algorithm works.
If you use a really dumb method of converting a binary64 to a decimal
string representing the same bit pattern, the decimal string can be very long. Example: x = 2**-1000 which is a valid binary64. It's the same
as (10/5)**-1000 or (10**-1000 / 5**-1000), so an exact decimal representation would be 93326...E-1000 where 93326... is the integer
5**1000 which is 699 digits long. Ugh.
Yes, I agree.I bet there is hardware out there for decimal arithmetic
Yes, there is, but only very expensive hardware (IBM mainframes and
such), as far as I can tell. They should build it into x64 and
everything else that has floating point.
On 9/28/26 8:11 AM, dxf wrote:
On 28/09/2026 9:47 pm, Krishna Myneni wrote:
On 9/27/26 10:52 PM, dxf wrote:
On 28/09/2026 3:37 am, Krishna Myneni wrote:
...
Therefore, if you do a conversion from a binary format to decimal characters, specifying the number of significant digits, it is incompatible with converting back to the original decimal format. However, if you use an internal IEEE decimal floating point format, it is possible to preserve the digits from the original string.
Forth's REPRESENT requires significant digits as an input since it is converting binary format to decimal digits. You can use it to implement a conversion with a specific number of decimal places, but you are not guaranteed to obtain the same digits as in the original decimal string.
AFAIR ANS didn't specify binary, leaving it open to things such as BCD fp. >>>> ANS stated purpose was to "serve as a basis for the future evolution of the
Forth language".-a Anything that arbitrarily excluded was avoided.
Sure, you can implement decimal format fp numbers and be compatible with the Forth standard. Then you can output floating point numbers in exactly the same way as they were input by a string of decimal digits, down to the last digit. You would then have to implement decimal format floating point arithmetic in software.
"REPRESENT requires significant digits as an input" is an interpretation I >>>> do not accept because it limits what REPRESENT can plainly do - as I said. >>>> I've not said REPRESENT can't be used to return an IEEE storage slot number
(all 750 digits) rounding it to some arbitrary figure the user has chosen >>>> - if that's what he wants.-a Only that I have no use and would rather not >>>> even see it.
Whether you accept it or not, that is the wording of the standard.
Sorry but no such wording exists.
It is fruitless for me to debate with you further about the meaning of the standard REPRESENT. In the future I will post some tests for REPRESENT and those in the Forth community who are interested in this topic can weigh in on their understanding of what the standard says.
For fixed point output, there is more code and REPRESENT is called more than once in my implementation of F.N, to obtain the properly rounded result to n decimal places.When you store the number in a different base than the base in which you input the number, a roundtrip conversion e.g. decimal to binary to decimal, which preserves the input to the least significant digit in the input is generally not possible, as noted in the IEEE 754 standard.
The problem is not with REPRESENT. Your issue is with not using an internal decimal format for floating point numbers. The IEEE 754 standard specifies 64-bit decimal formats as well.
I have no issue.-a REPRESENT as I've implemented it fulfils my needs.-a Will you
be posting your fixed-point code routine?-a Gforth's f.rdp required a chunk of
code be inserted to handle what its REPRESENT could not.-a I'm curious to see
how much code you expend handling the situation.
I will make F.N and F.RN and their string counterparts a part of the kForth packages in strings.4th after it is finished, along with tests for the string words. I will announce it here on c.l.f.
https://netlib.org/fp/dtoa.c
Krishna Myneni <krishna.myneni@ccreweb.org> writes:
Writing a small binary64 number like 2**-1000 as an exact decimalI don't follow what your saying here.
number the dumb way can take an awful lot of digits.
REPRESENT uses some kind of algorithm that, when the decimal precision
is >= 17, generates a decimal string that converts back to the same bit >pattern. I just mean I don't see off the top of my head how that
algorithm works.
If you use a really dumb method of converting a binary64 to a decimal
string representing the same bit pattern, the decimal string can be very >long. Example: x = 2**-1000 which is a valid binary64. It's the same
as (10/5)**-1000 or (10**-1000 / 5**-1000), so an exact decimal >representation would be 93326...E-1000 where 93326... is the integer
5**1000 which is 699 digits long. Ugh.
I bet there is hardware out there for decimal arithmetic
Yes, there is, but only very expensive hardware (IBM mainframes and
such), as far as I can tell. They should build it into x64 and
everything else that has floating point.
Since you mentioned tests here's GForth's REPRESENT vs. the one used
by DX-Forth and VFX using GForth's own example:
https://pastebin.com/7dFvBNNY
After you've posted your functions, I'll post my solution to the
challenge I gave in response to yours.
699 digits long. Ugh.That's not dumb, that's just exact.
If you really want decimal FP, there is a library from Intel that
implements it. The fact that it has not been touched since it was
introduced in 2008, despite having quite a bit of performance
improvement potential, tells me that nobody uses decimal FP who cares
for performance.
Why would anyone use decimal FP?
It's being sold as a solution for doing financial computations, due to financial rules.
But, you might say, IBM has implemented decimal FP, does that not
prove it's value? My explanation for that is that this is a feature
built in for selling to clueless managers.
anton@mips.complang.tuwien.ac.at (Anton Ertl) writes:
699 digits long. Ugh.That's not dumb, that's just exact.
Well, if you truncate the last 600 digits, what you keep will usually or >always still convert back to the same binary64. So can it fail? IDK.
anton@mips.complang.tuwien.ac.at (Anton Ertl) writes:
699 digits long. Ugh.That's not dumb, that's just exact.
Well, if you truncate the last 600 digits, what you keep will usually or >always still convert back to the same binary64. So can it fail? IDK.
If you really want decimal FP, there is a library from Intel that
implements it. The fact that it has not been touched since it was
introduced in 2008, despite having quite a bit of performance
improvement potential, tells me that nobody uses decimal FP who cares
for performance.
Right, it's software, let's say 100x slower than hardware FP.
Unusable if you care about FP performance.
If decimal were almost as fast as binary
(because the hardware does both)
Why would anyone use decimal FP?
Anyone who wants to calculate 1/5 and get 0.2.
It's being sold as a solution for doing financial computations, due to
financial rules.
I think that stuff is usually done in decimal fixed point, not FP.
But, you might say, IBM has implemented decimal FP, does that not
prove it's value? My explanation for that is that this is a feature
built in for selling to clueless managers.
You've probably seen this:
https://www.speleotrove.com/decimal/IEEE-cowlishaw-arith16.pdf
It explains some of the motivation.
Anyway we've had the "dark silicon"
problem for quite a while, so decimal FP seems like a natural candidate
to use some extra transistors.
When you use FP (including decimal FP), you should know that some FP
number are only approximations of the matimatical numbers, and some computation results are only approximations of the true computation
results. Learn to live with it. Decimal FP does not save you from
that.
dxf <dxforth@gmail.com> writes:
Since you mentioned tests here's GForth's REPRESENT vs. the one used
by DX-Forth and VFX using GForth's own example:
https://pastebin.com/7dFvBNNY
That code calls REPRESENT but doesn't include the implementation. Is
that available? I see a bunch of tests I but don't have much clarity
into why or whether it handles every input properly.
...
anton@mips.complang.tuwien.ac.at (Anton Ertl) writes:
699 digits long. Ugh.That's not dumb, that's just exact.
The ftoa.c that Krishna Myeni posted seemed rather ad hoc. This is a situation where I'd really want to use a theorem prover.
The reason has been explained a hundred times. A traditional fp numbers
has a finite binary representation. As 2 divides 10 this translates
to a finite decimal representation.
If you want an exact conversion rather than rounding... it is possible
for binary->decimal. For many FP numbers it takes many digits,
however.
Who knows how decimal FP is implemented in s390x? You are not allowed
to benchmark it
Unusable if you care about FP performance.There's the rub. If you care about FP performance, you use binary FP.
Nobody cares about the performance of decimal FP.
When you use FP (including decimal FP), you should know that some FP
number are only approximations of the matimatical numbers, and some computation results are only approximations of the true computation
results. Learn to live with it. Decimal FP does not save you from
that.
Let's see: Computer systems in 1961 (i.e., before binary won).
albert@spenarnc.xs4all.nl writes:
The reason has been explained a hundred times. A traditional fp numbers
has a finite binary representation. As 2 divides 10 this translates
to a finite decimal representation.
We know that there's a finite decimal representation, and in fact a 700
digit representation is exact. The question is first, whether a 100
digit approximation will ever fail to convert back to the same binary.
Then same thing for 17 digits. It looks like getting the right 17 digit approximation is very complicated.
The conversion has to be exact enough that binary->decimal->binary gets
back the binary that you started with. Doing that with 700 digits
obviously works. Doing it with 17 digits appears doable but
complicated.
On 30/09/2026 5:09 am, Paul Rubin wrote:
albert@spenarnc.xs4all.nl writes:
The reason has been explained a hundred times. A traditional fp numbers
has a finite binary representation. As 2 divides 10 this translates
to a finite decimal representation.
We know that there's a finite decimal representation, and in fact a 700 digit representation is exact. The question is first, whether a 100
digit approximation will ever fail to convert back to the same binary.
Then same thing for 17 digits. It looks like getting the right 17 digit approximation is very complicated.
According to an online IEEE double-prec calculator, Pi is:
3.14159265358979311599796346854E0
from the input:
3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679
Where would the world be without IEEE.
According to an online IEEE double-prec calculator, Pi is: 3.14159265358979311599796346854E0^^^^^^^^^^^^^^^^
from the input:^^^^^^^^^^^^^^^^
3.1415926535897932384626433832795...
On Wed, 30 Sep 2026 12:07:46 +1000
dxf <dxforth@gmail.com> wrote:
On 30/09/2026 5:09 am, Paul Rubin wrote:
albert@spenarnc.xs4all.nl writes:
The reason has been explained a hundred times. A traditional fp numbers >>>> has a finite binary representation. As 2 divides 10 this translates
to a finite decimal representation.
We know that there's a finite decimal representation, and in fact a 700
digit representation is exact. The question is first, whether a 100
digit approximation will ever fail to convert back to the same binary.
Then same thing for 17 digits. It looks like getting the right 17 digit >>> approximation is very complicated.
According to an online IEEE double-prec calculator, Pi is:
3.14159265358979311599796346854E0
from the input:
3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679
Where would the world be without IEEE.
Both these string when input into my system will produce
3.141592653589793e0
all 3 of then will produce the same binary representation
3.141592653589793e0 fh. 0x1.921FB54442D18p1 ok
I am using dtoa.c and have set it to the mode where it will return
the shortest string that converts back to the exact binary representation
I am pleased with that behavior!
interesting is of course if you apply some function to that pi approximation
3.141592653589793e0 fsin fs. 1.224646799147353e-16
BR
Peter
albert@spenarnc.xs4all.nl writes:
The reason has been explained a hundred times. A traditional fp numbers
has a finite binary representation. As 2 divides 10 this translates
to a finite decimal representation.
We know that there's a finite decimal representation, and in fact a 700
digit representation is exact. The question is first, whether a 100
digit approximation will ever fail to convert back to the same binary.
Then same thing for 17 digits. It looks like getting the right 17 digit >approximation is very complicated.
interesting is of course if you apply some function to that pi approximation
3.141592653589793e0 fsin fs. 1.224646799147353e-16
On 9/30/26 12:44 AM, peter wrote:
...
interesting is of course if you apply some function to that pi approximation
3.141592653589793e0 fsin fs. 1.224646799147353e-16
The glibc functions for sine and cosine fix the range reduction problem
for large angles, but do not fix the problem of inaccuracy near integer multiples of pi for sine, or integer multiples of pi/2 for cosine.
From https://notabs.org/fpuaccuracy/fpu-examples.htm:
sin near pi
argument 4000 C90F DAA2 2168 C235 (decimal 3.1415926535897932385)
actual BFBE ECE6 75D1 FC8F 8CBB (decimal -5.0165576126683320235E-20) x87 fpu BFBF 8000 0000 0000 0000 (decimal -5.42101086242752217E-20) error -1376283091369227076.6 ulp
cos near pi/2
argument 3FFF C90F DAA2 2168 C235 (decimal 1.5707963267948966193)
actual BFBD ECE6 75D1 FC8F 8CBB (decimal -2.5082788063341660117E-20) x87 fpu BFBE 8000 0000 0000 0000 (decimal -2.710505431213761085E-20) error -1376283091369227076.6 ulp
In terms of ulp the error is huge. See also other examples of fpu inaccuracies for sine and cosine at that page. The glibc sine function
has a few decimal digits improvement in accuracy near pi.
--
KM
On Wed, 30 Sep 2026 04:48:50 -0500...
From https://notabs.org/fpuaccuracy/fpu-examples.htm:
sin near pi
argument 4000 C90F DAA2 2168 C235 (decimal 3.1415926535897932385)
actual BFBE ECE6 75D1 FC8F 8CBB (decimal -5.0165576126683320235E-20) >> x87 fpu BFBF 8000 0000 0000 0000 (decimal -5.42101086242752217E-20)
error -1376283091369227076.6 ulp
cos near pi/2
argument 3FFF C90F DAA2 2168 C235 (decimal 1.5707963267948966193)
actual BFBD ECE6 75D1 FC8F 8CBB (decimal -2.5082788063341660117E-20) >> x87 fpu BFBE 8000 0000 0000 0000 (decimal -2.710505431213761085E-20)
error -1376283091369227076.6 ulp
In terms of ulp the error is huge. See also other examples of fpu
inaccuracies for sine and cosine at that page. The glibc sine function
has a few decimal digits improvement in accuracy near pi.
--
KM
I do not use the fpu but the core-math library. The problem is that we
input an approximation of pi to the sin function. That sine function
return the correctly rounded result for sin of that pi approximation.
I am looking to introduce the sinpi function (and similar for other trig) With them this rounding problem will be gone! but probably show up for
other input values
On 29/09/2026 1:14 am, Krishna Myneni wrote:
On 9/28/26 8:11 AM, dxf wrote:
On 28/09/2026 9:47 pm, Krishna Myneni wrote:
On 9/27/26 10:52 PM, dxf wrote:
On 28/09/2026 3:37 am, Krishna Myneni wrote:
...
Therefore, if you do a conversion from a binary format to decimal characters, specifying the number of significant digits, it is incompatible with converting back to the original decimal format. However, if you use an internal IEEE decimal floating point format, it is possible to preserve the digits from the original string.
Forth's REPRESENT requires significant digits as an input since it is converting binary format to decimal digits. You can use it to implement a conversion with a specific number of decimal places, but you are not guaranteed to obtain the same digits as in the original decimal string.
AFAIR ANS didn't specify binary, leaving it open to things such as BCD fp.
ANS stated purpose was to "serve as a basis for the future evolution of the
Forth language".a Anything that arbitrarily excluded was avoided.
Sure, you can implement decimal format fp numbers and be compatible with the Forth standard. Then you can output floating point numbers in exactly the same way as they were input by a string of decimal digits, down to the last digit. You would then have to implement decimal format floating point arithmetic in software.
"REPRESENT requires significant digits as an input" is an interpretation I
do not accept because it limits what REPRESENT can plainly do - as I said.
I've not said REPRESENT can't be used to return an IEEE storage slot number
(all 750 digits) rounding it to some arbitrary figure the user has chosen
- if that's what he wants.a Only that I have no use and would rather not >>>> even see it.
Whether you accept it or not, that is the wording of the standard.
Sorry but no such wording exists.
It is fruitless for me to debate with you further about the meaning of the standard REPRESENT. In the future I will post some tests for REPRESENT and those in the Forth community who are interested in this topic can weigh in on their understanding of what the standard says.
Whatever the standard said or had in mind 30 years ago, forth is now split thanks
to it and there's no going back. All that's left is the pragmatics - the pros and
cons of the implementations that exist. Debating scripture is for the religiously
minded.
For fixed point output, there is more code and REPRESENT is called more than once in my implementation of F.N, to obtain the properly rounded result to n decimal places.When you store the number in a different base than the base in which you input the number, a roundtrip conversion e.g. decimal to binary to decimal, which preserves the input to the least significant digit in the input is generally not possible, as noted in the IEEE 754 standard.
The problem is not with REPRESENT. Your issue is with not using an internal decimal format for floating point numbers. The IEEE 754 standard specifies 64-bit decimal formats as well.
I have no issue.a REPRESENT as I've implemented it fulfils my needs.a Will you
be posting your fixed-point code routine?a Gforth's f.rdp required a chunk of
code be inserted to handle what its REPRESENT could not.a I'm curious to see
how much code you expend handling the situation.
I will make F.N and F.RN and their string counterparts a part of the kForth packages in strings.4th after it is finished, along with tests for the string words. I will announce it here on c.l.f.
Since you mentioned tests here's GForth's REPRESENT vs. the one used by DX-Forth and
VFX using GForth's own example:
https://pastebin.com/7dFvBNNY
After you've posted your functions, I'll post my solution to the challenge I gave in
response to yours.
Okay. I understand your point better. The starting point is a 17 digit number. The only important point it is rational.
p/q can be approximated by r/s where the deviation is less that 1/q^2... Bottom line: you need 34 digits to get back at a 17 number.
I m pretty certain, but you need a formal proof, and there is a margin
e.g. 34 +1 needed.
The idea a GCC user can now ask for 'Pi' displayed to 30 places and it happily gives it - albeit a string of rubbish - is frightening. It's
a new level of 'user beware'.
On Wed, 30 Sep 2026 12:07:46 +1000numbers
dxf <dxforth@gmail.com> wrote:
On 30/09/2026 5:09 am, Paul Rubin wrote:
albert@spenarnc.xs4all.nl writes:
The reason has been explained a hundred times. A traditional fp
digithas a finite binary representation. As 2 divides 10 this translates
to a finite decimal representation.
We know that there's a finite decimal representation, and in fact a 700
digit representation is exact. The question is first, whether a 100
digit approximation will ever fail to convert back to the same binary.
Then same thing for 17 digits. It looks like getting the right 17
approximation is very complicated.
According to an online IEEE double-prec calculator, Pi is:
3.14159265358979311599796346854E0
from the input:
3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679
Where would the world be without IEEE.
Both these string when input into my system will produce
3.141592653589793e0
all 3 of then will produce the same binary representation
3.141592653589793e0 fh. 0x1.921FB54442D18p1 ok
I am using dtoa.c and have set it to the mode where it will return
the shortest string that converts back to the exact binary representation
I am pleased with that behavior!
interesting is of course if you apply some function to that piapproximation
3.141592653589793e0 fsin fs. 1.224646799147353e-16[..]
I am looking to introduce the sinpi function (and similar for other trig) >With them this rounding problem will be gone! but probably show up for
other input values
-a-a-a-a-a-a-a-a-a -4.7019774032891500318749461488887361922e-38-a okMy bad. Note that ">DD" should have been ">XD" :
\ print float to n decimals
create fpad 1024 allot
...
The question is first, whether a 100
digit approximation will ever fail to convert back to the same binary.
Then same thing for 17 digits.
It looks like getting the right 17 digit
approximation is very complicated.
On 9/30/26 10:42 AM, peter wrote:
\ print float to n decimals
create fpad 1024 allot
...
Hi Peter,
I tested your implementation of F.N under kForth-64 with my own set of
tests I've been developing for my implementation. One of the tests
failed with your code -- see output below (line breaks from kForth are suppressed). Incidentally, my tests are automated, but require the
string output version (F.N).
--
Krishna
=== begin test output ===
Test of Peter's implementation of F.N <peter.noreply@tin.it>
30 Sep 2026
0.0051e 0 f.n 0 ok
0.0051e 1 f.n 0.0 ok
0.0051e 2 f.n 0.01 ok
0.0051e 3 f.n 0.005 ok
0.0051e 4 f.n 0.0051 ok
0.0051e 5 f.n 0.00510 ok
0.0051e 17 f.n 0.00510000000000000 ok
2.0e-15 17 f.n 0.00000000000000200 ok
0.0e 0 f.n 0. ok
0.1e 0 f.n 0 ok
0.2e 0 f.n 0 ok
0.4e 0 f.n 0 ok
0.5e 0 f.n 0 ok
0.51e 0 f.n 1 ok
0.500000000000000001e 0 f.n 0 ok
0.50000000000000001e 0 f.n 0 ok
0.5000000000000001e 0 f.n 1 ok
0.6e 0 f.n 1 ok
0.9e 0 f.n 1 ok
1.0e 0 f.n 1. ok
1.4e 0 f.n 1. ok
1.4999999e 0 f.n 1. ok
1.5e 0 f.n 2. ok
2.5e 0 f.n 2. ok
3.5e 0 f.n 4. ok
-1100.2e 0 f.n -1100. ok
-1100.5e 0 f.n -1100. ok
-1101.5e 0 f.n -1102. ok
-1102.5e 0 f.n -1102. ok
2.01682663070034556e16 0 f.n 20168266307003456. ok
2.01682663070034556e16 20 f.n 20168266307003456.00000000000000000000 ok
0.5e 25 f.n 0.5000000000000000000000000 ok
0.625e 25 f.n 0.6250000000000000000000000 ok
0.625e 25 f.n 0.6250000000000000000000000 ok
-0.6e 4 f.n -0.6000 ok
-0.6e 16 f.n -0.6000000000000000 ok
-0.6e 17 f.n -0.59999999999999998 ok
-0.6e 23 f.n -0.59999999999999997779554 ok
-0.6e 25 f.n -0.5999999999999999777955395 ok
9.1e 3 f.n 9.100 ok
9.51e 1 f.n 9.5 ok
9.55e 1 f.n 9.6 ok
-9.66e 1 f.n -9.7 ok
99.995e 2 f.n 100.0 ok \ incorrect output
99.625e 2 f.n 99.62 ok
96.62500000000001e 2 f.n 96.63 ok
1.247777e3 0 f.n 1248. ok
1.247777e3 1 f.n 1247.8 ok
1.247777e3 2 f.n 1247.78 ok
1.247777e3 3 f.n 1247.777 ok
-5.0999913335e0 4 f.n -5.1000 ok
-5.0999913335e0 5 f.n -5.09999 ok
-5.0999913335e0 6 f.n -5.099991 ok
-5.0999913335e0 7 f.n -5.0999913 ok
-5.0999913335e0 8 f.n -5.09999133 ok
-5.0999913335e0 9 f.n -5.099991334 ok
9.599999999e8 0 f.n 960000000. ok
=== end of test output ===
On Wed, 30 Sep 2026 15:25:42 -0500
Krishna Myneni <krishna.myneni@ccreweb.org> wrote:
On 9/30/26 10:42 AM, peter wrote:
\ print float to n decimals
create fpad 1024 allot
...
Hi Peter,
I tested your implementation of F.N under kForth-64 with my own set of
tests I've been developing for my implementation. One of the tests
failed with your code -- see output below (line breaks from kForth are
suppressed). Incidentally, my tests are automated, but require the
string output version (F.N).
--
Krishna
Hi Krishna
Thanks for testing and providing your test cases. I downloaded and
compiled your latest kForth64 to confirm the result. It was there.
The strange thing is that I use also that test and have it working
correctly on lxf, lxf64, gforth, Swiftforth and Vfx.
I found the problem to be your REPRESENT that has a problem.
The problem is that it stores a 0 as a string ending.
I pre-fill the output buffer with char 48, the char 0.
The string ending overwrites this and stops type to print the
whole string.
This is also a buffer overflow as I asked for fpad 4 but
REPRESENT actually wrote 5 char to the buffer.
This test should work
123e45 0 0 represent
and give 48 0 -1 on the stack. But it segfaults instead.
My use of the buffer and pre-filling it might be questionable
but it should work and gives a simpler implementation as I
do not need any checks for how many decimals to print extra
due to rounding that increase the length of the integer part.
On 9/30/26 4:52 PM, peter wrote:
On Wed, 30 Sep 2026 15:25:42 -0500
Krishna Myneni <krishna.myneni@ccreweb.org> wrote:
On 9/30/26 10:42 AM, peter wrote:
\ print float to n decimals
create fpad 1024 allot
...
Hi Peter,
I tested your implementation of F.N under kForth-64 with my own set of
tests I've been developing for my implementation. One of the tests
failed with your code -- see output below (line breaks from kForth are
suppressed). Incidentally, my tests are automated, but require the
string output version (F.N).
--
Krishna
Hi Krishna
Thanks for testing and providing your test cases. I downloaded and
compiled your latest kForth64 to confirm the result. It was there.
The strange thing is that I use also that test and have it working
correctly on lxf, lxf64, gforth, Swiftforth and Vfx.
I found the problem to be your REPRESENT that has a problem.
The problem is that it stores a 0 as a string ending.
I pre-fill the output buffer with char 48, the char 0.
The string ending overwrites this and stops type to print the
whole string.
This is also a buffer overflow as I asked for fpad 4 but
REPRESENT actually wrote 5 char to the buffer.
...
On Tue, 29 Sep 2026 14:57:16 +1000
dxf <dxforth@gmail.com> wrote:
On 29/09/2026 1:14 am, Krishna Myneni wrote:
On 9/28/26 8:11 AM, dxf wrote:
On 28/09/2026 9:47 pm, Krishna Myneni wrote:
On 9/27/26 10:52 PM, dxf wrote:
On 28/09/2026 3:37 am, Krishna Myneni wrote:
...
Therefore, if you do a conversion from a binary format to decimal characters, specifying the number of significant digits, it is incompatible with converting back to the original decimal format. However, if you use an internal IEEE decimal floating point format, it is possible to preserve the digits from the original string.
Forth's REPRESENT requires significant digits as an input since it is converting binary format to decimal digits. You can use it to implement a conversion with a specific number of decimal places, but you are not guaranteed to obtain the same digits as in the original decimal string.
AFAIR ANS didn't specify binary, leaving it open to things such as BCD fp.
ANS stated purpose was to "serve as a basis for the future evolution of the
Forth language".-a Anything that arbitrarily excluded was avoided. >>>>>>
Sure, you can implement decimal format fp numbers and be compatible with the Forth standard. Then you can output floating point numbers in exactly the same way as they were input by a string of decimal digits, down to the last digit. You would then have to implement decimal format floating point arithmetic in software.
"REPRESENT requires significant digits as an input" is an interpretation I
do not accept because it limits what REPRESENT can plainly do - as I said.
I've not said REPRESENT can't be used to return an IEEE storage slot number
(all 750 digits) rounding it to some arbitrary figure the user has chosen
- if that's what he wants.-a Only that I have no use and would rather not
even see it.
Whether you accept it or not, that is the wording of the standard.
Sorry but no such wording exists.
It is fruitless for me to debate with you further about the meaning of the standard REPRESENT. In the future I will post some tests for REPRESENT and those in the Forth community who are interested in this topic can weigh in on their understanding of what the standard says.
Whatever the standard said or had in mind 30 years ago, forth is now split thanks
to it and there's no going back. All that's left is the pragmatics - the pros and
cons of the implementations that exist. Debating scripture is for the religiously
minded.
For fixed point output, there is more code and REPRESENT is called more than once in my implementation of F.N, to obtain the properly rounded result to n decimal places.When you store the number in a different base than the base in which you input the number, a roundtrip conversion e.g. decimal to binary to decimal, which preserves the input to the least significant digit in the input is generally not possible, as noted in the IEEE 754 standard.
The problem is not with REPRESENT. Your issue is with not using an internal decimal format for floating point numbers. The IEEE 754 standard specifies 64-bit decimal formats as well.
I have no issue.-a REPRESENT as I've implemented it fulfils my needs.-a Will you
be posting your fixed-point code routine?-a Gforth's f.rdp required a chunk of
code be inserted to handle what its REPRESENT could not.-a I'm curious to see
how much code you expend handling the situation.
I will make F.N and F.RN and their string counterparts a part of the kForth packages in strings.4th after it is finished, along with tests for the string words. I will announce it here on c.l.f.
Since you mentioned tests here's GForth's REPRESENT vs. the one used by DX-Forth and
VFX using GForth's own example:
https://pastebin.com/7dFvBNNY
After you've posted your functions, I'll post my solution to the challenge I gave in
response to yours.
I got interested and implemented a F.N that prints a float number with n decimals.
There are some special cases that needs to be taken care of. I think my implementation
works ok now. At least with my test cases. It needs a standard compliant represent.
It works on gforth, Vfx, swiftforth, lxf and lxf64. It supports also negative n to
some extent, reducing the significant digits on the integer part.
If I find this useful I will implement it as writing to a string instead of directly to the screen.
Paul Rubin <no.email@nospam.invalid> writes:
The question is first, whether a 100
digit approximation will ever fail to convert back to the same binary.
For binary64, no.
Then same thing for 17 digits.
That's a no for binary64, too. Now why is this the case?
Let's first get some basic tools:
: fnext {: f^ x :} x @ 1+ x ! x f@ ;
1e fnext 19 e.p \ 1.000000000000000222e
1e fnext 17 e.p \ 1.0000000000000002e
So 1 ulp is 2.22e-17 for 1e.
For cases where the first digit of the
decimal representation is >2e, 1 ulp is even larger.
So 1 ulp is 2.22e-17 for 1e. For cases where the first digit of the
decimal representation is >2e, 1 ulp is even larger.
"How to print floating-point numbers accurately"
Guy L. Steele, Jr., Jon L. White
For binary64 and "309 -307 differences", I get the following maximum...
and minimum values:
max relative ulp: 2.220446049250313e-16
min relative ulp: 1.1113793747425387e-16
the range of
integers where all integers can be represented ends at 2^53, i.e., >9007199254740992e.
=1e-16, so 17 decimal digits are enough to represent the binarymantissa, even if you combine that with huge exponents.
I don't know that I would characterize it as ad hoc. It's purpose is
to demonstrate that conversions of most numbers can be done more
efficiently than straight-forward methods. Anyway, the paper
describing it is here: https://ampl.com/_archive/first-website/REFS/rounding.pdf
Krishna Myneni <krishna.myneni@ccreweb.org> writes:
I don't know that I would characterize it as ad hoc. It's purpose is
to demonstrate that conversions of most numbers can be done more
efficiently than straight-forward methods. Anyway, the paper
describing it is here:
https://ampl.com/_archive/first-website/REFS/rounding.pdf
Thanks, if the complexity was mostly for efficiency then it's good to
know that a straightforward version is possible. On the other hand, the >paper by Steele and White isn't so simple either. I haven't read either >paper yet.
Start with the minimum representable positive number in decimal representation, a number with 751 decimal digits of mantissa for
binary64.
anton@mips.complang.tuwien.ac.at (Anton Ertl) writes:
Start with the minimum representable positive number in decimal
representation, a number with 751 decimal digits of mantissa for
binary64.
I guess that's "simple", but it's not what I had in mind by
straightforward.
On 9/30/26 4:52 PM, peter wrote:
On Wed, 30 Sep 2026 15:25:42 -0500
Krishna Myneni <krishna.myneni@ccreweb.org> wrote:
On 9/30/26 10:42 AM, peter wrote:
\ print float to n decimals
create fpad 1024 allot
...
Hi Peter,
I tested your implementation of F.N under kForth-64 with my own set of
tests I've been developing for my implementation. One of the tests
failed with your code -- see output below (line breaks from kForth are
suppressed). Incidentally, my tests are automated, but require the
string output version (F.N).
--
Krishna
Hi Krishna
Thanks for testing and providing your test cases. I downloaded and
compiled your latest kForth64 to confirm the result. It was there.
The strange thing is that I use also that test and have it working correctly on lxf, lxf64, gforth, Swiftforth and Vfx.
I found the problem to be your REPRESENT that has a problem.
The problem is that it stores a 0 as a string ending.
I pre-fill the output buffer with char 48, the char 0.
The string ending overwrites this and stops type to print the
whole string.
This is also a buffer overflow as I asked for fpad 4 but
REPRESENT actually wrote 5 char to the buffer.
This test should work
123e45 0 0 represent
and give 48 0 -1 on the stack. But it segfaults instead.
If you are passing 0 as the buffer address, kForth will complain it does
not have the correct type.
123e45 0 0 represent
Line 1: VM Error(-256): Not data type ADDR
123e45 0 0 represent
I don't quite see the problem with my REPRESENT.
create buf 100 allot
123e45 buf 0 represent .s
-1
0
48
ok
buf 4 dump
556DA9F1F020 : 31 00 00 00 ok
One character, '1', was returned, which is how dtoa() behaves even when
0 are requested. I'm not seeing a segfault. Can you give me the specific input that causes a segfault in kForth with your code?
Congrats on getting your F.N working first! My implementation was a
little more complicated than yours and I did not yet get all cases of negative decimal exponent working.
My use of the buffer and pre-filling it might be questionable
but it should work and gives a simpler implementation as I
do not need any checks for how many decimals to print extra
due to rounding that increase the length of the integer part.
If it works, I'm not complaining!
--
Krishna
On 1/10/2026 1:42 am, peter wrote:I get
On Tue, 29 Sep 2026 14:57:16 +1000
dxf <dxforth@gmail.com> wrote:
On 29/09/2026 1:14 am, Krishna Myneni wrote:
On 9/28/26 8:11 AM, dxf wrote:
On 28/09/2026 9:47 pm, Krishna Myneni wrote:
On 9/27/26 10:52 PM, dxf wrote:
On 28/09/2026 3:37 am, Krishna Myneni wrote:
...
Therefore, if you do a conversion from a binary format to decimal characters, specifying the number of significant digits, it is incompatible with converting back to the original decimal format. However, if you use an internal IEEE decimal floating point format, it is possible to preserve the digits from the original string.
Forth's REPRESENT requires significant digits as an input since it is converting binary format to decimal digits. You can use it to implement a conversion with a specific number of decimal places, but you are not guaranteed to obtain the same digits as in the original decimal string.
AFAIR ANS didn't specify binary, leaving it open to things such as BCD fp.
ANS stated purpose was to "serve as a basis for the future evolution of the
Forth language".a Anything that arbitrarily excluded was avoided. >>>>>>
Sure, you can implement decimal format fp numbers and be compatible with the Forth standard. Then you can output floating point numbers in exactly the same way as they were input by a string of decimal digits, down to the last digit. You would then have to implement decimal format floating point arithmetic in software.
"REPRESENT requires significant digits as an input" is an interpretation I
do not accept because it limits what REPRESENT can plainly do - as I said.
I've not said REPRESENT can't be used to return an IEEE storage slot number
(all 750 digits) rounding it to some arbitrary figure the user has chosen
- if that's what he wants.a Only that I have no use and would rather not
even see it.
Whether you accept it or not, that is the wording of the standard.
Sorry but no such wording exists.
It is fruitless for me to debate with you further about the meaning of the standard REPRESENT. In the future I will post some tests for REPRESENT and those in the Forth community who are interested in this topic can weigh in on their understanding of what the standard says.
Whatever the standard said or had in mind 30 years ago, forth is now split thanks
to it and there's no going back. All that's left is the pragmatics - the pros and
cons of the implementations that exist. Debating scripture is for the religiously
minded.
For fixed point output, there is more code and REPRESENT is called more than once in my implementation of F.N, to obtain the properly rounded result to n decimal places.When you store the number in a different base than the base in which you input the number, a roundtrip conversion e.g. decimal to binary to decimal, which preserves the input to the least significant digit in the input is generally not possible, as noted in the IEEE 754 standard.
The problem is not with REPRESENT. Your issue is with not using an internal decimal format for floating point numbers. The IEEE 754 standard specifies 64-bit decimal formats as well.
I have no issue.a REPRESENT as I've implemented it fulfils my needs.a Will you
be posting your fixed-point code routine?a Gforth's f.rdp required a chunk of
code be inserted to handle what its REPRESENT could not.a I'm curious to see
how much code you expend handling the situation.
I will make F.N and F.RN and their string counterparts a part of the kForth packages in strings.4th after it is finished, along with tests for the string words. I will announce it here on c.l.f.
Since you mentioned tests here's GForth's REPRESENT vs. the one used by DX-Forth and
VFX using GForth's own example:
https://pastebin.com/7dFvBNNY
After you've posted your functions, I'll post my solution to the challenge I gave in
response to yours.
I got interested and implemented a F.N that prints a float number with n decimals.
There are some special cases that needs to be taken care of. I think my implementation
works ok now. At least with my test cases. It needs a standard compliant represent.
It works on gforth, Vfx, swiftforth, lxf and lxf64. It supports also negative n to
some extent, reducing the significant digits on the integer part.
Good to see some more interest in the subject. With ANS only defining F. FS. FE.
few forths ever ventured further.
'Negative decimal places' didn't work for me (TYPE gets passed a negative value?).
AFAICS it truncates rather than rounds. Negative places isn't a feature I'd personally implement as I use n=-1 for something else. Otherwise your code generally works - even with the REPRESENT from DX-Forth and VFX. Your handling
of the 0.9/0.3 0 f.n case was of particular interest as many REPRESENT can't do
it natively. Which leads me to ask what you get for this...
1 set-precision
1e 0e f/ 0 f.n
since:
1 set-precision ok
1e 0e f/ 0 0 f.r +INF ok
FWIW SwiftForth gets stuff like this right but only because it bypasses REPRESENT
altogether.
Thanks for the test cases as I find writing such to be a chore. Redefining
: f.n 0 f.r space ;
on DX-Forth and VFX your tests passed with exception of 'negative places' which
it doesn't support. The last two tests overflowed the PNO buffer as was expected.
If I find this useful I will implement it as writing to a string instead of directly to the screen.
Indeed. String numeric output is decidedly lacking in many forths.
Thanks for participating!
| Sysop: | Amessyroom |
|---|---|
| Location: | Fayetteville, NC |
| Users: | 74 |
| Nodes: | 6 (0 / 6) |
| Uptime: | 122:20:45 |
| Calls: | 1,194 |
| Files: | 1,352 |
| Messages: | 290,355 |