• Hidden tools

    From dxf@dxforth@gmail.com to comp.lang.forth on Sun Sep 20 12:37:59 2026
    From Newsgroup: comp.lang.forth

    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.

    IMO the greater question is what tools has the Forth Standard (perhaps inadvertently) hidden that it shouldn't? 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.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Krishna Myneni@krishna.myneni@ccreweb.org to comp.lang.forth on Sat Sep 19 22:15:02 2026
    From Newsgroup: comp.lang.forth

    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.

    ...
    ... 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.

    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.

    --
    Krishna

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Krishna Myneni@krishna.myneni@ccreweb.org to comp.lang.forth on Sun Sep 20 00:13:01 2026
    From Newsgroup: comp.lang.forth

    On 9/19/26 10:15 PM, Krishna Myneni wrote:
    ...

    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.


    Here's code to convert a binary floating point number to a string in scientific notation using REPRESENT. You have to define the behavior for
    a bad conversion in check-ieee-special.

    Also, for standard Forth, @ is a synonym for a@ (used below)


    === begin fsdotstring.4th ===
    \ fsdotstring.4th
    \
    \ ($fs.) ( F: r ) ( -- caddr u)
    \
    \ K. Myneni, 19 Sep 2026
    \ Requires ans-words.4th for kForth

    55 CONSTANT MAX_PREC
    VARIABLE fslenlim
    VARIABLE cbuf0
    VARIABLE cbufptr
    VARIABLE sbufptr
    VARIABLE fsexp
    VARIABLE nexpchar
    FVARIABLE fs_r
    : check-ieee-special ( exp2b sign -- caddr u | throw )
    true ABORT" Floating Point Conversion Failed!"
    \ or use a throw code, or return a dummy string
    ;

    : ($fs.) ( F: r ) ( -- caddr u)
    PRECISION MAX_PREC MIN SET-PRECISION
    PAD dup cbuf0 ! cbufptr !
    PRECISION 8 + fslenlim !
    cbuf0 a@ fslenlim @ 2DUP + sbufptr ! BLANK
    FDUP fs_r F! \ for use with check-ieee-special
    sbufptr a@ PRECISION REPRESENT
    0= IF ( -- exp2b sign)
    check-ieee-special
    ELSE
    \ Handle sign
    IF [CHAR] - cbufptr a@ C! 1 cbufptr +! THEN
    IF [CHAR] - cbufptr a@ C! 1 cbufptr +! THEN
    \ Handle exponent
    fsexp !
    sbufptr a@ C@ cbufptr a@ C!
    1 sbufptr +! 1 cbufptr +!
    -1 fsexp +!
    [CHAR] . cbufptr a@ C! 1 cbufptr +!
    sbufptr a@ cbufptr a@ PRECISION 1- CMOVE
    PRECISION 1- cbufptr +!
    [CHAR] e cbufptr a@ C! 1 cbufptr +!
    fsexp @ 0< IF [CHAR] - ELSE [CHAR] + THEN
    cbufptr a@ C! 1 cbufptr +!
    fsexp @ abs DUP 100 < IF 2 ELSE 3 THEN nexpchar !
    S>D <#
    nexpchar @ 0 DO # LOOP #>
    >R cbufptr a@ R> CMOVE
    cbufptr a@ cbuf0 a@ - 1+ nexpchar @ +
    cbuf0 a@ SWAP
    THEN
    ;
    === end fsdotstring.4th ===

    And, here are some usage examples:

    === begin examples ===
    18 set-precision
    ok
    -1.0e0 facos ($fs.) type
    3.14159265358979312e+00 ok
    2.0e0 fln fnegate ($fs.) type
    -6.93147180559945286e-01 ok
    1.0e20 ($fs.) type
    1.00000000000000000e+20 ok
    1.23456e-308 ($fs.) type
    1.23456000000000001e-308 ok
    1.23456e308 ($fs.) type
    1.23456000000000008e+308 ok
    === end examples ===
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From dxf@dxforth@gmail.com to comp.lang.forth on Sun Sep 20 16:01:05 2026
    From Newsgroup: comp.lang.forth

    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:

    https://dxforth.mirrors.minimaltype.com/represent2.html

    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.

    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.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From anton@anton@mips.complang.tuwien.ac.at (Anton Ertl) to comp.lang.forth on Sun Sep 20 07:23:59 2026
    From Newsgroup: comp.lang.forth

    dxf <dxforth@gmail.com> writes:
    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.

    In Gforth we do it the other way round: In general we leave internal
    words accessible, but document only those that we intend to support
    (or, in some cases used to intend to support, but now deprecate).

    There are 5066 named words in the wordlists in Gforth. 1580 of those
    are currently documented (and the documentation for Gforth 1.0 is
    complete AFAICS).

    If users find an undcumented word (with, e.g., LOCATE), that he wants
    to use permanently, they can contact us suggesting to make this a
    supported (and documented) word. We may follow the suggestion, or if
    there are reasons not to support the word permanently, decline and
    maybe suggest an alternative way.

    - anton
    --
    M. Anton Ertl http://www.complang.tuwien.ac.at/anton/home.html
    comp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html
    New standard: https://forth-standard.org/
    EuroForth 2026 CFP: http://www.euroforth.org/ef26/cfp.html
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From anton@anton@mips.complang.tuwien.ac.at (Anton Ertl) to comp.lang.forth on Sun Sep 20 07:35:15 2026
    From Newsgroup: comp.lang.forth

    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.

    - anton
    --
    M. Anton Ertl http://www.complang.tuwien.ac.at/anton/home.html
    comp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html
    New standard: https://forth-standard.org/
    EuroForth 2026 CFP: http://www.euroforth.org/ef26/cfp.html
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From albert@albert@spenarnc.xs4all.nl to comp.lang.forth on Sun Sep 20 13:52:28 2026
    From Newsgroup: comp.lang.forth

    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.

    Groetjes Albert.
    --
    The Chinese government is satisfied with its military superiority over USA.
    The next 5 year plan has as primary goal to advance life expectancy
    over 80 years, like Western Europe.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Krishna Myneni@krishna.myneni@ccreweb.org to comp.lang.forth on Sun Sep 20 08:25:21 2026
    From Newsgroup: comp.lang.forth

    On 9/20/26 1:01 AM, dxf wrote:
    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:

    What are these issues?

    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



    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From dxf@dxforth@gmail.com to comp.lang.forth on Sun Sep 20 23:48:48 2026
    From Newsgroup: comp.lang.forth

    On 20/09/2026 9:52 pm, albert@spenarnc.xs4all.nl wrote:
    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.

    Once seen and used, it's impossible to go back ...

    (D.) ( d -- c-addr u ) factor of D. providing (U.) (.)

    S.R ( c-addr u width -- ) factor of D.R

    TRIM ( c-addr u1 char -- c-addr u2 -- ) factor of -TRAILING

    HELD ( -- c-addr u ) factor of #>

    ?ABORT ( n c-addr u -- ) factor of ABORT"

    CHAR ( u -- char ) factor of #

    DIGIT ( char radix -- u true | char false ) factor of >NUMBER

    MU* ( ud1 u -- ud2 ) factor of >NUMBER

    MU/MOD ( ud u -- urem udquot ) factor of #

    RDROP UNNEST ( R: x -- ) factor of EXIT

    2RDROP ( R: x1 x2 -- ) synonym of UNLOOP

    SKIP SCAN ( a u char ) factors of WORD PARSE


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Krishna Myneni@krishna.myneni@ccreweb.org to comp.lang.forth on Sun Sep 20 08:50:49 2026
    From Newsgroup: comp.lang.forth

    On 9/20/26 2:35 AM, Anton Ertl wrote:
    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:


    I use a word called F.RD (defined in strings.4th) which is for fixed
    point output format only. Some Forths apparently have the word F.R . I
    don't know whether or not F.RD and F.R have the same behavior. I will be reimplementing F.RD using REPRESENT so maybe I will see what you found cumbersome about it.

    REPRESENT is one shot -- it converts all of the digits requested in the significand string with nearest rounding, and an implied decimal point position at zero. It also returns the sign and decimal exponent. Some
    people appear to be confused that the returned decimal exponent depends
    on both the binary exponent and the number of digits (string length)
    argument to REPRESENT. After REPRESENT the rest is just character/string processing to put the digits, decimal point, sign, the exponent marker,
    sign, and the exponent (if not fixed form) in the desired format.

    I posted my string output version of FS. written using REPRESENT and it
    is straight-forward. The .E format, with leading sign and decimal point
    is even more straight-forward.

    Common usage names for the conversion to various decimal string formats
    would be nice, however.
    | 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.


    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.

    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).


    A system can set a limit on maximum number of output digits in the significand, even if it is not full precision. The rounding is what's important, however, and I think that's where the cost comes from.
    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.


    Yes, I didn't notice for a long time. Until I needed it. On the linux
    systems, the glibc routines took care of proper rounding in the
    conversions. Users not doing numerical work may not notice or care.

    --
    Krishna

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Krishna Myneni@krishna.myneni@ccreweb.org to comp.lang.forth on Sun Sep 20 09:29:18 2026
    From Newsgroup: comp.lang.forth

    On 9/20/26 1:01 AM, dxf wrote:
    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.



    One important use case is whenever you need to check how far your
    calculation is in ulp against a reference value. An example is the
    calculation of a high order spherical bessel function with a large
    argument -- this one came up in my own work. More generally, knowing the accuracy of computing special functions across a range of arguments, in
    ulp, is needed for estimating the accuracy of end results of the
    calculation.

    Typically the reference value is presented in decimal form. Converting
    the reference from decimal string to binary form to determine the
    difference in ulp. If the conversion from decimal string to binary is
    itself bad (not within 1 ulp of the closest binary in the chosen binary format), then you will not have a correct ulp error calculation.

    Similarly, if you want to know how many decimal digits are accurate in
    your computed binary floating point number, you should output them
    correctly rounded to the maximum number of significant digits for your
    binary format precision. This can't be done with a REPRESENT that fails
    to do accurate binary to decimal conversion.

    --
    KM


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From dxf@dxforth@gmail.com to comp.lang.forth on Mon Sep 21 01:02:47 2026
    From Newsgroup: comp.lang.forth

    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:
    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:

    What are these issues?
    ...

    - 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 or
    padding, when flag2 is false.

    - no provision for rounding entire significand.

    The last two being the worst.

    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

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Krishna Myneni@krishna.myneni@ccreweb.org to comp.lang.forth on Sun Sep 20 11:10:00 2026
    From Newsgroup: comp.lang.forth

    On 9/20/26 10:02 AM, dxf wrote:
    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:
    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:

    What are these issues?
    ...

    - does not specify exponent value (n) in the case of 0.0E .

    - nothing stated regarding values for n and flag1 when flag2 is false.


    The Forth standard for REPRESENT does not specify what n (the decimal
    exponent for the implied .E format) should be, probably because an error
    code will depend on assuming a particular format for the floating point number. Maybe a case can be made that a sign is always determinable and
    should be returned in flag1, even when flag2 is FALSE.

    dtoa() returns a special value for n (9999) when the dp floating point
    number is either NAN or INF. kForth's REPRESENT does return that for n,
    so that a conversion routine such as ($FS) can return the appropriate
    string. It also returns a flag indicating the sign bit.
    - nothing stated regarding the graphic string's length, alignment or
    padding, when flag2 is false.
    It is implementation dependent. The flag tells you your conversion has
    failed. You need more information about the floating point format to do anything, which is not specified in the standard.

    - no provision for rounding entire significand.What do you mean by rounding the *entire* significand? For IEEE double
    precision, the significand can have in excess of 750 digits for the
    smallest magnitude non-zero subnormal number. In general, the number of significant decimal digits for a given binary floating number is
    variable, with 16 being a minimum, and 17 needed for round-trip from
    binary to decimal and back. However, the rounding depends on the number
    of digits requested, via the length of the string buffer. The standard
    is explicit and without ambiguity on this point.

    "The character string shall consist of the u most significant digits
    of the significand represented as a decimal fraction with the implied
    decimal point to the left of the first digit, and the first digit zero
    only if all digits are zero. The significand is rounded to u digits
    following the rCLround to nearestrCY rule; n is adjusted, if necessary,
    to correspond to the rounded magnitude of the significand."


    The last two being the worst.

    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.

    --
    Krishna


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From anton@anton@mips.complang.tuwien.ac.at (Anton Ertl) to comp.lang.forth on Sun Sep 20 15:31:17 2026
    From Newsgroup: comp.lang.forth

    Krishna Myneni <krishna.myneni@ccreweb.org> writes:
    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.

    F.RDP chooses either exponential notation (where R and the sign and
    exponent determine how many digits are displayed, or non-exponential
    notation (aka fixed-point notation), where D determines the number of
    digits behind the decimal point. P determines whether the
    non-exponential notation shows enough significant digits that it can
    be used, and determines whether the exponential notation shows enough significant digits.

    In non-exponential notation, D and the exponent determine how many
    digits we need from ecvt()/REPRESENT. With fcvt(), just providing D
    would be good enough. And with ecvt()/REPRESENT, we may need to try
    out two exponents to get the desired result: E.g., with R=8, D=5
    printing 9.999995 may either have to convert to 10.00000 or to 9.99999 (actually the former, but we don't know this at this point), and with REPRESENT, you may have to try a mantissa length of 7 and 6.

    And then you may find out that the number does not satisfy the
    requirements for non-exponential notation, so you switch to
    exponential notation.

    In exponential notation, the size of the exponent determines how many
    digits are left for the mantissa, but the exponent may depend on the
    number of digits left for the mantissa. E.g., consider 9.9999e9: If
    you have only 7 chars total field width, this becomes 1.00e10, but
    with 8 chars total field width, it becomes 9.9999e9. So you have to
    try several mantissa widths. I am not sure if an fcvt() variant would
    help here.

    What might be helpful for eliminating the tries is a second output
    array containing flags, that indicates whether one would round up the corresponding digit if the number was cut off at this digit. It might
    go with another word that rounds up the mantissa at that digit (plus
    carry effects).

    Common usage names for the conversion to various decimal string formats >would be nice, however.

    I typically use >STRING-EXECUTE. That's expensive, but one word deals
    with all the words that output directly. And I have never needed (F.)
    etc., and not used F. with >STRING-EXECUTE, either.

    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.

    Yes, sprintf() is (too?) high-level.

    - anton
    --
    M. Anton Ertl http://www.complang.tuwien.ac.at/anton/home.html
    comp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html
    New standard: https://forth-standard.org/
    EuroForth 2026 CFP: http://www.euroforth.org/ef26/cfp.html
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From dxf@dxforth@gmail.com to comp.lang.forth on Mon Sep 21 13:02:45 2026
    From Newsgroup: comp.lang.forth

    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.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Krishna Myneni@krishna.myneni@ccreweb.org to comp.lang.forth on Sun Sep 20 22:43:25 2026
    From Newsgroup: comp.lang.forth

    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.

    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.


    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.

    If the string length passed to REPRESENT is zero, here's what I get in
    kForth:

    0.9e0 pad 0 REPRESENT
    ok
    .s

    -1
    0
    0

    The true flag means the conversion has succeeded, but zero digits for
    the significand have been requested, so there is nothing to print.
    Similarly for the other example of 0.4e.

    For the case of a nan, the output looks fine to me, since you are using
    an IEEE format.

    In kForth,

    0e 0e F/ PAD 1 REPRESENT

    -1
    0
    1
    ok
    0e 0e f/ fs.



    bye



    --
    KM

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Krishna Myneni@krishna.myneni@ccreweb.org to comp.lang.forth on Sun Sep 20 22:48:54 2026
    From Newsgroup: comp.lang.forth

    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.

    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.


    For each of these examples, please show what is being passed to
    REPRESENT and what is returned on the stack. Your examples don't show
    how REPRESENT is being used.

    --
    Krishna


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From dxf@dxforth@gmail.com to comp.lang.forth on Mon Sep 21 15:41:36 2026
    From Newsgroup: comp.lang.forth

    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
    <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 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 000000000000000

    <ok> go ok 9373 2 < \ result from (f.)


    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.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Krishna Myneni@krishna.myneni@ccreweb.org to comp.lang.forth on Mon Sep 21 22:16:09 2026
    From Newsgroup: comp.lang.forth

    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 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

    This couldn't be the entire set of args to REPRESENT. 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?

    <ok> go
    <BREAK> stack= 1 0 -1 < \ output from REPRESENT


    Conversion succeeded, sign is zero, and decimal exponent is 1.

    <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


    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.

    <ok> go ok 9373 2 < \ 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.

    0.4e 0 (f.) \ 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
    -1
    0
    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
    4 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.

    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

    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.

    0e 0e F/ PAD 1 REPRESENT .S

    0
    -1
    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.


    <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.

    That's consistent with the current standard, which says it is
    implementation defined.

    --
    Krishna


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From dxf@dxforth@gmail.com to comp.lang.forth on Tue Sep 22 17:16:56 2026
    From Newsgroup: comp.lang.forth

    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.


    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.

    -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

    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.

    ANS make no mention of "fail" "error" or exception. All it says is that when r is
    not "in the implementation-defined range of floating-point numbers" then flag2 is
    zero and a graphic string shall be provided. For systems that support IEEE, a NAN
    applied to REPRESENT giving a NAN output can hardly be said to have failed. I don't
    expect REPRESENT to "fail".


    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.12.6.1.2143 references "+infinity or nan" so these were at least considered.



    -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 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.

    That's consistent with the current standard, which says it is implementation defined.

    Except ANS says nothing regarding the string's placement, padding, or how
    to retrieve it. Here's what some implementation give:

    1 set-precision ok
    0e 0e f/ f. - ok

    1 set-precision ok
    0e 0e f/ f. N ok

    C could do better.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Krishna Myneni@krishna.myneni@ccreweb.org to comp.lang.forth on Tue Sep 22 07:34:33 2026
    From Newsgroup: comp.lang.forth

    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 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.


    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 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.


    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.

    --
    KM

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From dxf@dxforth@gmail.com to comp.lang.forth on Wed Sep 23 00:16:33 2026
    From Newsgroup: comp.lang.forth

    On 22/09/2026 10:34 pm, Krishna Myneni wrote:
    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..."

    fpi pad 5 represent pad 15 dump
    195FE0 | 33 31 34 31 36 30 30 30 30 30 30 30 30 30 30 |314160000000000| ok...

    There it is - PI converted to a 15 character numeric string containing the
    5 most significant digits. Want only 5 characters, then take only 5. I see nothing in the spec that excludes this.

    -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.

    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.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Krishna Myneni@krishna.myneni@ccreweb.org to comp.lang.forth on Tue Sep 22 11:44:11 2026
    From Newsgroup: comp.lang.forth

    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. 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.


    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.

    --
    KM



    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From dxf@dxforth@gmail.com to comp.lang.forth on Wed Sep 23 11:55:24 2026
    From Newsgroup: comp.lang.forth

    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

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Krishna Myneni@krishna.myneni@ccreweb.org to comp.lang.forth on Wed Sep 23 16:12:23 2026
    From Newsgroup: comp.lang.forth

    On 9/22/26 8:55 PM, dxf wrote:
    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


    This is basically how my current fixed point float to string conversion
    word F>FPSTR works:

    \ Convert r to a formatted fixed point string with
    \ n decimal places, 0 <= n <= 17.
    \ WARNING: Requesting a number fixed point decimal places which
    \ results in total number of digits > 17 will give
    \ incorrect results, e.g. "65536.9921875e 15 f>fpstr type"
    \ will output garbage (20 digits are being requested).
    : f>fpstr ( n -- a u ) ( F: r -- ) \ ( r n -- a u )
    0 max 17 min >r 10e r@ s>f f**
    f* fround f>d dup -rot dabs
    <# r> 0 ?DO # LOOP [char] . hold #s rot sign #> ;

    It is a factor of F.RD but it fails if more than 17 decimal places are requested.

    The implementation of F.RD using REPRESENT (without using pictured
    number output words) is coming along fine. The logic is settling into
    place, but it's not done yet.

    --
    Krishna

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Krishna Myneni@krishna.myneni@ccreweb.org to comp.lang.forth on Wed Sep 23 17:03:15 2026
    From Newsgroup: comp.lang.forth

    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. 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. 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 #>
    ;

    What's the definition of #EXP? Isn't that the source of your grief with writing properly rounded formatting words?

    --KM


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From dxf@dxforth@gmail.com to comp.lang.forth on Thu Sep 24 11:34:29 2026
    From Newsgroup: comp.lang.forth

    On 24/09/2026 8:03 am, Krishna Myneni wrote:
    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 claimed
    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 #>
    ;

    What's the definition of #EXP?

    It simply returns the exponent of r and is equivalent to:

    ( F: r -- r ) ( -- exp )
    FDUP F0= IF 0 EXIT THEN
    FDUP FABS FLOG FLOOR F>S

    AFAIK the demo version of Swiftforth comes with the fp sources should folks require
    more detail.

    Isn't that the source of your grief with writing properly rounded formatting words?

    I've had no grief since employing the results shown here - rather than quashing them
    as most REPRESENT implementations (including Swiftforth's) do. My curiosity only
    extends to seeing how you intend to handle the lack. I've seen how others have done it.
    There's always the chance you may come up with something new. There is no 'last word'
    on anything.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Hans Bezemer@the.beez.speaks@gmail.com to comp.lang.forth on Thu Sep 24 17:51:02 2026
    From Newsgroup: comp.lang.forth

    On 24-09-2026 03:34, dxf wrote:
    ( F: r -- r ) ( -- exp )
    FDUP F0= IF 0 EXIT THEN
    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
    fdup f0= if 0 ;then frexp 1- >r 1 s>f 2 s>f f/ f- f2*
    r> s>f f+ (log2>log10) floor f>s
    ;

    Hans Bezemer
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From dxf@dxforth@gmail.com to comp.lang.forth on Fri Sep 25 03:18:32 2026
    From Newsgroup: comp.lang.forth

    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" 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
    ;

    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.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Hans Bezemer@the.beez.speaks@gmail.com to comp.lang.forth on Fri Sep 25 09:09:07 2026
    From Newsgroup: comp.lang.forth

    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 ( 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.


    It seems to me like DX-Forth doesn't support IEEE singles. If it were,
    this might be a solution:

    fvariable (ieee32)

    : frexp
    base @ >r hex (ieee32) dup f! @ dup 17 rshift 0ff and 07e - >r
    0807fffff and 03f000000 or (ieee32) tuck ! f@ r> r> base !
    ;

    Note: UNTESTED! I have currently no Forth compiler that seems to support
    this format.

    Hans Bezemer
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Hans Bezemer@the.beez.speaks@gmail.com to comp.lang.forth on Fri Sep 25 11:10:53 2026
    From Newsgroup: comp.lang.forth

    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 ( 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.


    These are tested -- and I think they're quite reasonable:

    fvariable (ieee32)

    base @ >r hex

    : frexp
    fdup f0= if fdrop 0 s>f 0 exit then
    (ieee32) dup f! @ dup 17 rshift 0ff and dup
    0ff = if drop drop (ieee32) f@ 0 exit then
    07e - >r 0807fffff and 03f000000 or (ieee32) tuck ! f@ r>
    ;

    base !

    fvariable (ieee64)

    base @ >r hex

    : frexp
    fdup f0= if fdrop 0 s>f 0 exit then
    (ieee64) dup f! @ dup 34 rshift 07ff and dup
    07ff = if drop drop (ieee64) f@ 0 exit then
    03fe - >r 0800fffffffffffff and 03fe0000000000000 or (ieee64) tuck !
    f@ r>
    ;

    base !

    Hans Bezemer
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Hans Bezemer@the.beez.speaks@gmail.com to comp.lang.forth on Fri Sep 25 11:39:13 2026
    From Newsgroup: comp.lang.forth

    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 ( 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.


    BTW, if somebody looking for a fairly fast and generic LDEXP, here it is:

    : ** ( n1 n2 -- n1^n2)
    dup 1 = if drop exit then
    dup 0< abort" Negative exponent"
    1 >r begin dup 1 and if over r> * >r then 2/ swap dup * swap dup 0= until
    drop drop r>
    ;

    : ldexp
    dup 0= if drop exit then dup 0< dup >r if abs then
    2 swap ** s>f r> if 1 s>f fswap f/ then f*
    ;

    Hans Bezemer
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From dxf@dxforth@gmail.com to comp.lang.forth on Fri Sep 25 20:40:19 2026
    From Newsgroup: comp.lang.forth

    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"
    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.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Hans Bezemer@the.beez.speaks@gmail.com to comp.lang.forth on Fri Sep 25 13:39:40 2026
    From Newsgroup: comp.lang.forth

    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 ( 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.

    Okay, the ultimate -- with subnormal number support:

    0 1 2constant 2^64

    fvariable (ieee64)

    base @ >r hex

    : frexp
    fdup f0= if fdrop 0 s>f 0 exit then
    (ieee64) dup f! @ dup 34 rshift 07ff and
    dup 07ff = if drop drop (ieee64) f@ 0 exit then
    dup 0= if drop drop (ieee64) f@ 2^64 d>f f* recurse 40 - exit then
    03fe - >r 0800fffffffffffff and 03fe0000000000000 or (ieee64) tuck !
    f@ r>
    ;

    base !

    Hans Bezemer
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Hans Bezemer@the.beez.speaks@gmail.com to comp.lang.forth on Fri Sep 25 14:02:57 2026
    From Newsgroup: comp.lang.forth

    On 25-09-2026 12:40, dxf wrote:
    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.


    16 constant cell-bits

    \ tested
    : DAND ( xd1 xd2 -- xd3 ) rot and >r and r> ;
    : DOR ( xd1 xd2 -- xd3 ) rot or >r or r> ;

    : drshift
    dup 0> 0= if drop exit then
    dup cell-bits - dup 0< 0= if >r drop nip r> rshift 0 exit then drop
    >r dup 0 invert cell-bits r@ - dup >r rshift and r> lshift swap
    r@ rshift swap rot ( spin) r> rshift or swap
    ;

    \ untested
    : frexp ( f1 -- f2 n)
    fdup f0= if fdrop 0 s>f 0 exit then
    (ieee32) f! (ieee32) 2@ 2dup 17 drshift 0ff. dand d>s
    0ff = if drop 2drop (ieee32) f@ 0 exit then
    07e - >r 0807fffff. dand 03f000000. dor (ieee32) tuck ! f@ r>
    ;

    Does this help a bit? UNTESTED, which should be expected.

    Hans Bezemer
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From dxf@dxforth@gmail.com to comp.lang.forth on Sat Sep 26 00:20:38 2026
    From Newsgroup: comp.lang.forth

    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.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Hans Bezemer@the.beez.speaks@gmail.com to comp.lang.forth on Fri Sep 25 16:26:39 2026
    From Newsgroup: comp.lang.forth

    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.

    It was quite a battle, but I succeeded:

    ---8<---
    16 constant cell-bits
    fvariable (ieee32)

    : dand ( xd1 xd2 -- xd3 ) rot and >r and r> ;
    : do5 ( xd1 xd2 -- xd3 ) rot or >r or r> ;

    : drshift
    dup 0> 0= if drop exit then
    dup cell-bits - dup 0< 0= if >r drop nip r> rshift 0 exit then drop
    >r dup 0 invert cell-bits r@ - dup >r rshift and r> lshift swap
    r@ rshift swap rot ( spin) r> rshift or swap
    ;

    hex

    : frexp ( f1 -- f2 n)
    fdup f0= if fdrop 0 s>f 0 exit then
    (ieee32) f! (ieee32) 2@ swap 2dup 17 drshift cr drop ff and
    dup ff = if drop 2drop (ieee32) f@ 0 exit then
    7e - >r 807fffff. dand 3f000000. dor (ieee32) 2! (ieee32) f@ swap r>
    ;

    decimal
    ---8<---

    Hans Bezemer

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Hans Bezemer@the.beez.speaks@gmail.com to comp.lang.forth on Fri Sep 25 16:32:32 2026
    From Newsgroup: comp.lang.forth

    On 25-09-2026 16:26, Hans Bezemer wrote:
    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:
    (tiny typo corrected). We were close! But you won! :-)

    16 constant cell-bits
    fvariable (ieee32)

    : dand ( xd1 xd2 -- xd3 ) rot and >r and r> ;
    : dor ( xd1 xd2 -- xd3 ) rot or >r or r> ;

    : drshift
    dup 0> 0= if drop exit then
    dup cell-bits - dup 0< 0= if >r drop nip r> rshift 0 exit then drop
    >r dup 0 invert cell-bits r@ - dup >r rshift and r> lshift swap
    r@ rshift swap rot ( spin) r> rshift or swap
    ;

    hex

    : frexp ( f1 -- f2 n)
    fdup f0= if fdrop 0 s>f 0 exit then
    (ieee32) f! (ieee32) 2@ swap 2dup 17 drshift cr drop ff and
    dup ff = if drop 2drop (ieee32) f@ 0 exit then
    7e - >r 807fffff. dand 3f000000. dor (ieee32) 2! (ieee32) f@ swap r>
    ;

    decimal

    Hans Bezemer

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Hans Bezemer@the.beez.speaks@gmail.com to comp.lang.forth on Fri Sep 25 17:37:32 2026
    From Newsgroup: comp.lang.forth

    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 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.

    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

    HB
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From dxf@dxforth@gmail.com to comp.lang.forth on Sat Sep 26 15:07:27 2026
    From Newsgroup: comp.lang.forth

    On 26/09/2026 1:37 am, Hans Bezemer wrote:
    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.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Hans Bezemer@the.beez.speaks@gmail.com to comp.lang.forth on Sat Sep 26 13:16:46 2026
    From Newsgroup: comp.lang.forth

    On 26-09-2026 07:07, dxf wrote:
    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.

    Frankly, I think it's a feature that holds very little use for those of
    us doing "government work". 4tH's IEEE 754 routine simply won't handle
    them either.

    However, if they start working again, you know where you can get FREXP
    support for them ;-)

    Hans Bezemer

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Krishna Myneni@krishna.myneni@ccreweb.org to comp.lang.forth on Sat Sep 26 07:09:16 2026
    From Newsgroup: comp.lang.forth

    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.5e 25 f.n
    0.5000000000000000000000000 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 25 f.n
    -0.5999999999999999777955395 ok

    -0.6e 23 f.n
    -0.59999999999999997779554 ok \ rounding to 23 dp

    99.995e 2 f.n
    100.00 ok

    99.625e 2 f.n
    99.62 ok

    96.62500000000001e 2 f.n
    96.63 ok

    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.

    --
    KM


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From dxf@dxforth@gmail.com to comp.lang.forth on Sun Sep 27 01:36:09 2026
    From Newsgroup: comp.lang.forth

    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.

    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

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Krishna Myneni@krishna.myneni@ccreweb.org to comp.lang.forth on Sat Sep 26 11:25:21 2026
    From Newsgroup: comp.lang.forth

    On 9/26/26 10:36 AM, dxf wrote:
    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.

    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.

    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.

    --
    KM

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Krishna Myneni@krishna.myneni@ccreweb.org to comp.lang.forth on Sat Sep 26 12:47:28 2026
    From Newsgroup: comp.lang.forth

    On 9/26/26 11:25 AM, Krishna Myneni wrote:
    On 9/26/26 10:36 AM, dxf wrote:
    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-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.

    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.

    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.

    Some n = 0 tests

    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
    1e-1 0 f.n 0. 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

    On the last test where we print out 20 decimal places, it appears we
    stumbled onto an exactly representable number (in double precision).

    I still have to fix the logic for negative exponents below -1. The implementation is nearly done and it's easy to turn the character output
    into a string output to make (f.n).

    --
    KM
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From dxf@dxforth@gmail.com to comp.lang.forth on Sun Sep 27 06:17:28 2026
    From Newsgroup: comp.lang.forth

    On 27/09/2026 2:25 am, Krishna Myneni wrote:
    On 9/26/26 10:36 AM, dxf wrote:
    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-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.

    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.

    If someone does know what GCC printf displays, I'd be interested.

    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.

    Logical would be letting REPRESENT do what it can.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Krishna Myneni@krishna.myneni@ccreweb.org to comp.lang.forth on Sat Sep 26 16:24:13 2026
    From Newsgroup: comp.lang.forth

    On 9/26/26 3:17 PM, dxf wrote:
    On 27/09/2026 2:25 am, Krishna Myneni wrote:
    ...
    -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.

    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.

    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)
    {
    double x = 0.6;

    printf("\nx: %.25g\n", x);
    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.

    --
    Krishna



    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Krishna Myneni@krishna.myneni@ccreweb.org to comp.lang.forth on Sat Sep 26 16:07:09 2026
    From Newsgroup: comp.lang.forth

    On 9/26/26 3:17 PM, dxf wrote:
    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.


    For every use of REPRESENT, I purposely inserted "1 MAX" before
    REPRESENT to ensure the argument u, the number of *significant digits*,
    is always non-zero. My REPRESENT calls the dtoa() function from David
    Gay's dtoa.c, which treats u = 0 exactly the same as u = 1, so I didn't
    have to do so, but other implementations of REPRESENT may do something
    wierd -- it is undefined behavior in the standard.

    I can't think of any argument to be made for standardizing the behavior
    of u = 0, except maybe to handle user error, or to make it convenient
    for programmers not to add their own error prevention like "1 MAX" after u.

    --
    KM
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From dxf@dxforth@gmail.com to comp.lang.forth on Sun Sep 27 15:47:05 2026
    From Newsgroup: comp.lang.forth

    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:
    ...
    -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.

    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.

    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.

    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.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Krishna Myneni@krishna.myneni@ccreweb.org to comp.lang.forth on Sun Sep 27 10:11:12 2026
    From Newsgroup: comp.lang.forth

    On 9/27/26 12:47 AM, dxf wrote:
    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:
    ...
    -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.

    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.

    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.

    What I do know is that GCC's implementation of binary to decimal
    conversion is what any serious language for numerical calculations
    should implement. It's output capability allows you to determine the
    absolute error of the binary representation for a converted base 10
    string. When you enter "0.6e0", or any other real number, and this
    string is converted to the internal binary representation, the actual
    number being represented is

    0.60 + epsilon

    The ability to output enough decimal digits to allow you to determine
    epsilon in decimal form is a convenience feature, because one does not
    always have at hand what the internal binary representation should be.
    In some applications it is necessary to know this to determine the order
    of magnitude error in the result of a calculation. It is not required by
    IEEE 754.

    --
    KM

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Krishna Myneni@krishna.myneni@ccreweb.org to comp.lang.forth on Sun Sep 27 12:37:47 2026
    From Newsgroup: comp.lang.forth

    On 9/27/26 10:11 AM, Krishna Myneni wrote:
    ...
    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.


    From the 2019 IEEE Standard for Floating-Point Arithmetic (IEEE Std
    754-2019) document,

    section 5.12 Details of conversion between floating-point data and
    external character sequences:

    "Implementations shall provide conversions between each supported binary format and external decimal character sequences such that, under roundTiesToEven, conversion from the supported format to external
    decimal character sequence and back recovers the original floating-point representation, except that a signaling NaN might be converted to a
    quiet NaN. See 5.12.1 and 5.12.2 for details."

    From section 5.4.2:

    "If the conversion is to a format in a different radix or to a narrower precision in the same radix, the result shall be rounded as specified in Clause 4. Conversion to a format with the same radix but wider precision
    and range is always exact.

    For inexact conversions from binary to decimal formats, the preferred
    exponent is the least possible. For exact conversions from binary to
    decimal formats, the preferred exponent is 0."

    5.12.2 External decimal character sequences representing finite numbers 5.12.2.0 An implementation shall provide operations that convert from
    all supported floating-point formats to external decimal character
    sequences (see 5.4.2). For finite numbers, these operations can be
    thought of as parameterized by the source format, the number of
    significant digits in the result (if specified), and whether the quantum
    is preserved (for decimal formats). *Observe that specifying the number
    of significant digits and specifying quantum preservation are mutually incompatible.*

    The definitions of "quantum" and "radix" are:

    quantum: The quantum of a finite floating-point representation is the
    value of a unit in the last position of its significand. This is equal
    to the radix raised to the exponent q, which is used when the ignificand
    is regarded as an integer.

    radix: The base for the representation of binary or decimal
    floating-point numbers, two or ten.

    Note the phrase, "unit in the last position" or commonly referred to as
    "ulp".

    I emphasized the sentence, *Observe that specifying the number of
    significant digits and specifying quantum preservation are mutually incompatible.*

    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.


    That's all that I can find in the IEEE 754 document about binary to
    decimal string conversions.

    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.

    --
    KM

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From dxf@dxforth@gmail.com to comp.lang.forth on Mon Sep 28 13:52:08 2026
    From Newsgroup: comp.lang.forth

    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.

    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.

    Forth's Robert L. Smith was a member of the 1985 committee. For F-PC he donated his 8087 fp package. This was before ANS though he did participate
    - in what specifically I don't know. Too late to find out now.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Krishna Myneni@krishna.myneni@ccreweb.org to comp.lang.forth on Mon Sep 28 06:47:46 2026
    From Newsgroup: comp.lang.forth

    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". 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. 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.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From dxf@dxforth@gmail.com to comp.lang.forth on Mon Sep 28 23:11:30 2026
    From Newsgroup: comp.lang.forth

    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.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Krishna Myneni@krishna.myneni@ccreweb.org to comp.lang.forth on Mon Sep 28 10:14:22 2026
    From Newsgroup: comp.lang.forth

    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.

    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.

    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.

    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.

    --
    KM


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Paul Rubin@no.email@nospam.invalid to comp.lang.forth on Mon Sep 28 13:55:18 2026
    From Newsgroup: comp.lang.forth

    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.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Krishna Myneni@krishna.myneni@ccreweb.org to comp.lang.forth on Mon Sep 28 17:11:33 2026
    From Newsgroup: comp.lang.forth

    On 9/28/26 3:55 PM, Paul Rubin wrote:
    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.


    binary->decimal->binary only recovers the same bit pattern if you
    request enough significant digits from REPRESENT. In the caddr u
    arguments for the string buffer to REPRESENT, the u specifies the number
    of signficant digits to which the binary representation is rounded (to nearest). Take the following example

    fvariable r
    create cbuf 32 allot

    17 set-precision
    pi fs.
    pi fs.
    3.1415926535897931e+00 ok

    pi r df! r @ hex u. decimal \ on a 64-bit system
    400921FB54442D18 ok

    cbuf 16 erase
    \ Request the 7 leading significant digits of pi
    pi cbuf 7 represent 2drop .
    1 ok \ this is the decimal exponent
    cbuf 12 dump
    5572F264EC20 : 33 31 34 31 35 39 33 00 00 00 00 00 ok

    The converted digits are "3141593" and the decimal point is implicitly
    to the left of the first digit, and the decimal exponent is 1, which was returned, along with the sign of the number and a conversion success
    flag, but we dropped the latter two.

    We can turn the buffer contents into the appropriate decimal string for conversion back into binary, "0.3141593e1" and pass that to >FLOAT

    s" 0.3141593e1" >float drop r df! r @ fs.
    3.1415929999999999e+00 ok
    r @ hex u. decimal
    400921FB82C2BD7F ok

    Obviously not the same binary pattern because we did not request enough significant digits. However, if we repeat this for u = 17 to REPRESENT,
    then we recover the same bit pattern.

    cbuf 18 erase pi cbuf 17 represent
    ok
    cbuf 20 dump

    5572F264EC20 : 33 31 34 31 35 39 32 36 35 33 35 38 39 37
    39 33 3141592653589793
    5572F264EC30 : 31 00 00 00 ok

    s" 0.31415926535897931e1" >float drop r df! r @ hex u. decimal
    400921FB54442D18 ok

    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.


    I don't follow what your saying here.
    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.


    I bet there is hardware out there for decimal arithmetic, otherwise I
    don't know why the IEEE 754 standards committee would standardize the
    decimal formats like decimal64.

    --
    KM


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Paul Rubin@no.email@nospam.invalid to comp.lang.forth on Mon Sep 28 17:51:11 2026
    From Newsgroup: comp.lang.forth

    Krishna Myneni <krishna.myneni@ccreweb.org> writes:
    Writing a small binary64 number like 2**-1000 as an exact decimal
    number the dumb way can take an awful lot of digits.
    I don't follow what your saying here.

    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.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Krishna Myneni@krishna.myneni@ccreweb.org to comp.lang.forth on Mon Sep 28 21:15:12 2026
    From Newsgroup: comp.lang.forth

    On 9/28/26 7:51 PM, Paul Rubin wrote:
    Krishna Myneni <krishna.myneni@ccreweb.org> writes:
    Writing a small binary64 number like 2**-1000 as an exact decimal
    number the dumb way can take an awful lot of digits.
    I don't follow what your saying here.

    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, there is well-know code, used widely, for both converting binary
    floating point to decimal strings and vice-versa. I've been talking
    about it for a while here on c.l.f.:

    https://netlib.org/fp/dtoa.c

    It provides two functions, strtod() for decimal string to binary64
    conversion and dtoa() for binary 64 to decimal string conversion. I use
    it in kForth-32/64/Win32.

    It uses its own built-in big number arithmetic, and is relatively
    lightweight.

    We can do this entirely in Forth as well using the FSL big number
    arithmetic package by Len Zettel, with some additions.

    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.
    Yes, I agree.

    --
    KM

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From dxf@dxforth@gmail.com to comp.lang.forth on Tue Sep 29 14:57:16 2026
    From Newsgroup: comp.lang.forth

    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.


    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.

    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.

    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.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Paul Rubin@no.email@nospam.invalid to comp.lang.forth on Mon Sep 28 23:03:58 2026
    From Newsgroup: comp.lang.forth

    Krishna Myneni <krishna.myneni@ccreweb.org> writes:
    https://netlib.org/fp/dtoa.c

    OMG. Thanks. Little-known fact: that code went backwards in time and
    inspired a series of famous novels by H. P. Lovecraft. Kidding.

    I figured that the generic case could be simple but I didn't see how to
    be sure about the edge cases. That was much messier than I had
    imagined. I wonder if there's a cleaner way to do it.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From anton@anton@mips.complang.tuwien.ac.at (Anton Ertl) to comp.lang.forth on Tue Sep 29 05:48:32 2026
    From Newsgroup: comp.lang.forth

    Paul Rubin <no.email@nospam.invalid> writes:
    Krishna Myneni <krishna.myneni@ccreweb.org> writes:
    Writing a small binary64 number like 2**-1000 as an exact decimal
    number the dumb way can take an awful lot of digits.
    I don't follow what your saying here.

    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.

    There are a number of papers on that for several different algorithms.
    When I read the first one (intending to implement REPRESENT from
    scratch), it looked very complicated, so I just implemented REPRESENT
    as calling ecvt() (and later ecvt_r()), and left the implementation
    from scratch for another day.

    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.

    That's not dumb, that's just exact.

    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.

    No, they should not. 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 the
    financial rules prescribe fixed point computations, because they were
    designed at times when there was no floating point, neither decimal
    nor otherwise. Decimal FP caters for these applications by being more
    like fixed point and not normalizing at every step, but why would you
    use decimal FP when you actually want fixed point? Fixed point is
    easier and more efficient to implement, even with a power-of-10 as
    scaling factor.

    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
    --
    M. Anton Ertl http://www.complang.tuwien.ac.at/anton/home.html
    comp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html
    New standard: https://forth-standard.org/
    EuroForth 2026 CFP: http://www.euroforth.org/ef26/cfp.html
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Paul Rubin@no.email@nospam.invalid to comp.lang.forth on Mon Sep 28 23:23:39 2026
    From Newsgroup: comp.lang.forth

    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.

    After you've posted your functions, I'll post my solution to the
    challenge I gave in response to yours.

    I've lost track of what those challenges are but I've come to understand
    that REPRESENT (or ftoa) is a messy problem. No the answer doesn't
    involve printing 700+ digits ;). For binary32 one can test all possible inputs, so maybe that's a good way to try out simple approaches and see
    where they go wrong. There may be some latitude in how to implement
    atof to complement ftoa while still keeping 1 ulp accuracy.

    I don't think it's in the Forth spirit to implement decimal FP in
    software just to make REPRESENT work, if the hardware supports binary
    FP.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Paul Rubin@no.email@nospam.invalid to comp.lang.forth on Tue Sep 29 01:28:09 2026
    From Newsgroup: comp.lang.forth

    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.

    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.

    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. With optimization it might be only
    50x slower. That's about the same situation, so fine, use binary and
    accept the annoyances. If decimal were almost as fast as binary
    (because the hardware does both), then decimal suddenly gets a lot more attractive.

    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. I
    can say I just used Python's very slow decimal arithmetic library just
    to get nicer looking output from a throwaway script whose speed I didn't
    care about. It wasn't anything about 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.

    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.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From albert@albert@spenarnc.xs4all.nl to comp.lang.forth on Tue Sep 29 11:48:25 2026
    From Newsgroup: comp.lang.forth

    In article <878q4kfome.fsf@nightsong.com>,
    Paul Rubin <no.email@nospam.invalid> wrote:
    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.

    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.

    Groetjes Albert
    --
    The Chinese government is satisfied with its military superiority over USA.
    The next 5 year plan has as primary goal to advance life expectancy
    over 80 years, like Western Europe.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From anton@anton@mips.complang.tuwien.ac.at (Anton Ertl) to comp.lang.forth on Tue Sep 29 08:50:03 2026
    From Newsgroup: comp.lang.forth

    Paul Rubin <no.email@nospam.invalid> writes:
    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.

    17 digits are enough for converting back to binary64. But you usually
    round on the conversion to decimal, and you usually round on the
    conversion to binary. If you want an exact conversion rather than
    rounding, that's often not possible for decimal->binary (e.g., for
    0.1), but it is possible for binary->decimal. For many FP numbers it
    takes many digits, however.

    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.

    Who knows how decimal FP is implemented in s390x? You are not allowed
    to benchmark it, and I daresay that good performance is not a common
    reason for disallowing benchmarking. But the best thing about
    not-benchmarking is that you can let your prospective victim^H^H^H^H^H^Hcustomer let his imagination run wild with vastly
    inflated speedup numbers. You are just bycatch in this game.

    Maybe IBM implements decimal FP in microcode; then it will be no
    faster than software. Anyway, the numbers I have read about the Intel
    library are 200 cycles for addition or so, on 2008-vintage Intel
    hardware, probably somewhat faster now. But even with these 200
    cycles, I don't expect any hardware implementation that does it in 2
    cycles.

    Plus, the performance of the library can be improved quite a bit.

    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. That's why the
    Intel library has not been improved, and I expect that the hardware
    that IBM has thrown at it is limited, and even if the performance is
    better than for Intel's library, it is still unusable if you care
    about FP performance.

    If decimal were almost as fast as binary
    (because the hardware does both)

    It isn't.

    Why would anyone use decimal FP?

    Anyone who wants to calculate 1/5 and get 0.2.

    And then you want to calculate 1/3, or sqrt(2), or e or pi.

    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.

    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.

    Exactly.

    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.

    Let's see: Computer systems in 1961 (i.e., before binary won). A
    financial calculation (5% or $0.70) carried out in FP. This is
    exactly the case that I mentioned about financial rules and fixed
    point. Contents of database fields, where he even claims integers for
    his cause (which can be represented exactly as binary64 FP numbers as
    long as they are <=2^53, and as binary128 FP numbers as long as the
    are <=2^112).

    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.

    Dark silicon is a power supply and heat-removal problem for useful
    silicon. The solution is not to throw silicon at useless
    functionality like decimal FP.

    CPU core designers have usually produced big designs in the
    expectation of having more transistors to play with, and have often
    had to go on a "silicon diet" because their designs became too large
    and too expensive. These days, Apple sells hardware with three tiers
    of CPU cores, the biggest ones for maximum single- or dual-thread
    performance, middle ones and small ones. ARM now even has four tiers
    of CPU cores with different sizes, but I think that their customers
    combine only three of those cores on one SoC. If they just wanted to
    consume silicon, they would use just the biggest cores. They don't
    because wafers processed with the latest lithography process are
    expensive.

    The solution to the power problem is to disable parts of the chip that
    are not needed at the moment and to use lower voltage (and lower clock frequency) when more of the chip is in use, among other measures.

    - anton
    --
    M. Anton Ertl http://www.complang.tuwien.ac.at/anton/home.html
    comp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html
    New standard: https://forth-standard.org/
    EuroForth 2026 CFP: http://www.euroforth.org/ef26/cfp.html
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Krishna Myneni@krishna.myneni@ccreweb.org to comp.lang.forth on Tue Sep 29 06:15:45 2026
    From Newsgroup: comp.lang.forth

    On 9/29/26 3:50 AM, Anton Ertl wrote:
    ...
    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.


    To a certain extent it does, within a exponent range limited to the
    number of significant decimal digits. However, with 64-bit computing, I suppose there is no gain over using fixed point integer arithmetic.

    A good illustration of why you can't output binary fp numbers in decimal digits naively, whether the output format is scientific or fixed point:

    1 SET-PRECISION
    5.5e1 FS. 6.e+01 ok
    5.5e0 FS. 6.e+00 ok
    5.5e-1 FS. 6.e-01 ok
    5.5e-2 FS. 6.e-02 ok
    5.5e-3 FS. 5.e-03 ok \ <-- not what you expect by rounding rule
    5.5e-4 FS. 6.e-04 ok
    5.5e-5 FS. 6.e-05 ok
    5.5e-6 FS. 5.e-06 ok \ <--
    5.5e-7 FS. 6.e-07 ok
    5.5e-8 FS. 6.e-08 ok
    5.5e-9 FS. 5.e-09 ok \ <--

    Of course, it's the internal binary representation which is the cause of
    the apparent rounding failure:

    17 SET-PRECISION
    5.5e1 FS. 5.5000000000000000e+01 ok
    5.5e0 FS. 5.5000000000000000e+00 ok
    5.5e-1 FS. 5.5000000000000004e-01 ok
    5.5e-2 FS. 5.5000000000000000e-02 ok
    5.5e-3 FS. 5.4999999999999997e-03 ok \ <--
    5.5e-4 FS. 5.5000000000000003e-04 ok
    5.5e-5 FS. 5.5000000000000002e-05 ok
    5.5e-6 FS. 5.4999999999999999e-06 ok \ <--
    5.5e-7 FS. 5.5000000000000003e-07 ok
    etc.

    When you output a binary fp number in fixed point format with a small
    number of decimal places, you are likely to run into such issues e.g.
    5.5e-3 output in fixed point format with 3 decimal places.

    --
    KM



    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From dxf@dxforth@gmail.com to comp.lang.forth on Tue Sep 29 21:28:13 2026
    From Newsgroup: comp.lang.forth

    On 29/09/2026 4:23 pm, Paul Rubin wrote:
    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.
    ...

    My interest in REPRESENT (and its issues) are strictly ANS-related.
    Nothing to do with IEEE, its precision requirements, or the recent
    interest by some forthers in using REPRESENT to effect the display
    of IEEE numbers to the nth digit.

    If it's the former you are asking about, the issue I encountered in
    2005 was the inability of most REPRESENT implementations to handle
    input where u was zero or some low value. Imagine having no fcvt(),
    an ecvt() that produced who-knows-what in the case of nan/inf, and
    you wanted to write something like sprintf(). That was more-or-less
    the situation I was faced with in 2005. As was Gforth when it came
    to write F.RDP. The situation is no better today.

    In my case I re-drafted the ANS spec to clarify what wasn't and the
    include the features I considered essential. The latest version being:

    Represent_35.txt

    It includes a simple implementation. Otherwise, there's:

    FPOUT_Swiftforth4.zip

    https://drive.google.com/drive/folders/1kh2WcPUc3hQpLcz7TQ-YQiowrozvxfGw

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Krishna Myneni@krishna.myneni@ccreweb.org to comp.lang.forth on Tue Sep 29 06:39:43 2026
    From Newsgroup: comp.lang.forth

    On 9/29/26 3:28 AM, Paul Rubin wrote:
    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.

    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


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Paul Rubin@no.email@nospam.invalid to comp.lang.forth on Tue Sep 29 12:09:23 2026
    From Newsgroup: comp.lang.forth

    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.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Paul Rubin@no.email@nospam.invalid to comp.lang.forth on Tue Sep 29 12:58:14 2026
    From Newsgroup: comp.lang.forth

    anton@mips.complang.tuwien.ac.at (Anton Ertl) writes:
    If you want an exact conversion rather than rounding... it is possible
    for binary->decimal. For many FP numbers it takes many digits,
    however.

    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.

    Who knows how decimal FP is implemented in s390x? You are not allowed
    to benchmark it

    It looks like decimal FP is available on POWER6 and POWER7 (IDK about
    later iterations). Nothing stops you from benchmarking those. It was
    once possible to rent POWER9 servers by the hour from scaleway.com, but
    not any more, it appears.

    Unusable if you care about FP performance.
    There's the rub. If you care about FP performance, you use binary FP.

    Obviously there's a continuum of how much you care. If you REALLY care,
    first of all you use a GPU if you can, and also use single precision if
    you can, or even half-precision. Or use x86 SIMD instructions, etc.
    Most of the time, regular x86 double precision is fast enough, so
    e.g. gforth doesn't offer anything else. You've already accepted maybe
    10x slowdown by using gforth doubles instead of GCC SIMD intrinsics. If
    using decimal64 slows your FP operations by another 2x, that's probably
    fine, but 100x is much more likely to not be fine.

    Nobody cares about the performance of decimal FP.

    This is circular reasoning. If the x86 did decimal and binary FP at the
    exact same speed, some users who care about speed will choose decimal to
    just to get nicer looking output. Next question is how much decimal
    slowdown they'll tolerate before switching back to binary. 5% slower?
    They probably won't switch. 2x slower? Maybe some will switch. 1000x?
    All of them switch.

    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.

    Despite that, I found myself using decimal math in Python just a week or
    so ago, because I wanted to print the dimensions of something in inches
    and wanted to display 3.2 instead of 3.1999... or whatever it was.
    Nothing to do with finance, and no irrational numbers. Yes I could have
    fooled around with formatting but it was simpler to just use decimal,
    which did the right thing automatically. It's true that I didn't care
    about speed for that program.

    The right question to ask is, if python or gforth or gcc had a
    "--decimal" command line option that selected decimal FP at a 10%
    slowdown, would anyone use it? IMHO, yes, quite a few would.

    Let's see: Computer systems in 1961 (i.e., before binary won).

    Binary won because bits were expensive in that era. I was about to
    write "transistors were expensive" but vacuum tube computers were still
    a thing then. Even today, lots of small computers (ARM Cortex M4F)
    support IEEE binary32 in hardware but don't support binary64. With
    bigger computers (x86) we generally use binary64 without thinking about
    it. Decimal is just more of the same.

    I see https://silminds.com/files/dl/decimal-floating-point-for-future-processors.pdf claims:

    A benchmarking study [14] estimates that many financial applications
    spend over 75% of their execution time in Decimal Floating Point
    (DFP) functions. For this class of applications, the speedup
    resulting from the use of a fast hardware implementation versus a
    pure software implementation ranges from a factor of 5.3 to a factor
    of 31.2 depending on the specific application running [14].

    As you say though, I don't understand why those applications weren't
    using fixed point.

    This page is also interesting: https://www.speleotrove.com/decimal/
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From dxf@dxforth@gmail.com to comp.lang.forth on Wed Sep 30 12:07:46 2026
    From Newsgroup: comp.lang.forth

    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.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Lars Brinkhoff@lars.spam@nocrew.org to comp.lang.forth on Wed Sep 30 05:40:23 2026
    From Newsgroup: comp.lang.forth

    Paul Rubin wrote:
    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.

    Scanning this paper, maybe yes, a bit complicated.

    "How to print floating-point numbers accurately"
    Guy L. Steele, Jr., Jon L. White
    https://dl.acm.org/doi/10.1145/93542.93559 https://lists.nongnu.org/archive/html/gcl-devel/2012-10/pdfkieTlklRzN.pdf
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From peter@peter.noreply@tin.it to comp.lang.forth on Wed Sep 30 07:44:58 2026
    From Newsgroup: comp.lang.forth

    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

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Paul Rubin@no.email@nospam.invalid to comp.lang.forth on Wed Sep 30 00:46:38 2026
    From Newsgroup: comp.lang.forth

    dxf <dxforth@gmail.com> writes:
    According to an online IEEE double-prec calculator, Pi is: 3.14159265358979311599796346854E0
    ^^^^^^^^^^^^^^^^
    from the input:
    3.1415926535897932384626433832795...
    ^^^^^^^^^^^^^^^^

    It looks like they start differing at the 17th significant digit, about
    what I'd expect for IEEE double which has 53 mantissa bits.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From dxf@dxforth@gmail.com to comp.lang.forth on Wed Sep 30 18:01:33 2026
    From Newsgroup: comp.lang.forth

    On 30/09/2026 3:44 pm, peter wrote:
    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!

    Yes, and I imagine x87 comes close without any additional resource. It's on account of IEEE's requirements that Intel used 80-bits internally. Programmers would go on to exploit it, saying 'what the heck, I'll just use 80 bits and forget about IEEE'. But with x87 deprecated, users are increasingly forced to use IEEE. The empire strikes back.

    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'.

    interesting is of course if you apply some function to that pi approximation

    3.141592653589793e0 fsin fs. 1.224646799147353e-16

    BR
    Peter


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From albert@albert@spenarnc.xs4all.nl to comp.lang.forth on Wed Sep 30 10:18:20 2026
    From Newsgroup: comp.lang.forth

    In article <874if7g9i4.fsf@nightsong.com>,
    Paul Rubin <no.email@nospam.invalid> 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.

    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.
    If you can approximate r/s with a precision less than 1/q^2 than you have identified the original number. That can be accomplished by a decimal
    expansion of r/s.

    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.

    Groetjes Albert
    --
    The Chinese government is satisfied with its military superiority over USA.
    The next 5 year plan has as primary goal to advance life expectancy
    over 80 years, like Western Europe.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Krishna Myneni@krishna.myneni@ccreweb.org to comp.lang.forth on Wed Sep 30 04:48:50 2026
    From Newsgroup: comp.lang.forth

    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
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From peter@peter.noreply@tin.it to comp.lang.forth on Wed Sep 30 13:01:27 2026
    From Newsgroup: comp.lang.forth

    On Wed, 30 Sep 2026 04:48:50 -0500
    Krishna Myneni <krishna.myneni@ccreweb.org> wrote:

    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

    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

    BR
    Peter

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Krishna Myneni@krishna.myneni@ccreweb.org to comp.lang.forth on Wed Sep 30 09:49:55 2026
    From Newsgroup: comp.lang.forth

    On 9/30/26 6:01 AM, peter wrote:
    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


    For the glibc sine and cosine functions, I was planning to map the
    absolute error around the exactly representable numbers near pi.

    The glibc computation of sine near pi uses range reduction and then uses
    a Taylor series, with coefficients from a lookup table.


    /*-------------------------- 2.426265<|x|< 105414350
    ----------------------*/
    else if (k < 0x419921FB)
    {
    n = reduce_sincos (x, &a, &da);
    retval = do_sincos (a, da, n);
    } /* else if (k < 0x419921FB ) */


    do_sincos() calls do_sin() which has the following description,

    /* Given a number partitioned into X and DX, this function computes the
    sine of
    the number by combining the sin and cos of X (as computed by a
    variation of
    the Taylor series) with the values looked up from the sin/cos table
    to get
    the result. */

    Should be able to figure out why the Taylor series near pi has this much error, but it's not high on my list of things to do right now.


    --
    KM

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From peter@peter.noreply@tin.it to comp.lang.forth on Wed Sep 30 17:42:00 2026
    From Newsgroup: comp.lang.forth

    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.


    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.

    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.

    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.
    BR
    Peter
    \ print float to n decimals
    create fpad 1024 allot
    : f.n-case-00 ( F:fp -- ) \ exp<=0 n=0 round to +-1 or 0
    0.5e f> if '1' else '0' then emit ;

    : f.n-case-e+n<0 ( F:fp n -- )
    fdrop
    ." 0."
    0 ?do '0' emit loop ;
    : f.n-case-e+n=0 ( F:fp n e -- )
    fdup abs s>f falog f* fswap \ prepare fp for rounding
    1- f.n-case-e+n<0 \ print 1 less zero
    f.n-case-00 ;

    : f.n-case-e>0 ( F:fp n e -- )
    over + \ n e+n
    fpad 1024 '0' fill
    fpad swap represent 2drop \ n e'
    dup >r \ n e' r: e'
    fpad swap type '.' emit \ n
    fpad r> + \ n fpad+e'
    swap type ;

    : f.n-case-e<=0 ( F:fp n e -- )
    over + 1 max \ n e+n
    fpad 1024 '0' fill
    fpad swap represent 2drop \ n e'
    dup >r \ n e' r: e'
    ." 0." abs 0 ?do '0' emit loop
    fpad swap r> + \ fpad n+e'
    type ;

    : f.n ( F:fp n -- )
    fdup fpad 32 represent \ find exp and sign
    0= if 2drop drop f. exit then \ nan or inf
    if '-' emit fabs then
    over 0< if
    swap over 1- negate max swap else \ limit negative n
    swap over 1024 swap - min swap then \ limit positive n
    2dup 0 <= swap 0= and \ n e f
    if 2drop f.n-case-00 exit then
    2dup + 0<
    if drop f.n-case-e+n<0 exit then
    2dup + 0=
    if f.n-case-e+n=0 exit then
    dup 0>
    if f.n-case-e>0 exit then
    f.n-case-e<=0 ;

    \ 0 [IF]
    \ Test cases
    : testing cr begin refill while source 2dup type space evaluate cr repeat ; testing
    0.9e 0 f.n
    0.3e 0 f.n
    -0.9e 0 f.n
    -0.3e 0 f.n
    0.123e 0 f.n
    0.123e-1 1 f.n
    0.123e-2 2 f.n
    0.123e-3 3 f.n
    0.823e 0 f.n
    0.823e-1 1 f.n
    0.823e-2 2 f.n
    0.823e-3 3 f.n
    0.1368e 3 f.n
    0.1368e-1 3 f.n
    0.1368e-2 3 f.n
    0.1368e-3 3 f.n
    0.1368e-4 3 f.n
    -0.8368e 3 f.n
    -0.8368e-1 3 f.n
    -0.8368e-2 3 f.n
    -0.8368e-3 3 f.n
    -0.8368e-4 3 f.n
    123.4567e 3 f.n
    123.4567e 2 f.n
    123.4567e 1 f.n
    123.4567e 0 f.n
    123.4567e -1 f.n
    123.4567e -2 f.n
    123.4567e -3 f.n
    99.995e 3 f.n
    99.995e 2 f.n
    99.995e 1 f.n
    5.2345678e-1 10 f.n
    5.2345678e-2 10 f.n
    5.2345678e-3 10 f.n
    5.2345678e-4 10 f.n
    5.2345678e-5 10 f.n
    5.2345678e-6 10 f.n
    5.2345678e-7 10 f.n
    5.2345678e-8 10 f.n
    5.2345678e-9 10 f.n
    5.2345678e-10 10 f.n
    5.2345678e-11 10 f.n
    5.2345678e-12 10 f.n
    123e300 10 f.n
    123e-300 305 f.n
    \ [THEN]
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Paul Rubin@no.email@nospam.invalid to comp.lang.forth on Wed Sep 30 09:34:29 2026
    From Newsgroup: comp.lang.forth

    albert@spenarnc.xs4all.nl writes:
    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 a bit confused here, is r/s the decimal or the binary
    representation? This sounds like it's about decimal->binary->decimal
    which is some cases can't be exact, so I'm not worrying about that case
    for now. The requirement is an exact binary->decimal->binary where the
    decimal representation has 17 sig. figures. This must be possible since
    IEEE requires it. A mathematical proof would be nice. Question then is
    how to do the conversion.

    I guess a simple but dumb approach might amount to numerical root
    finding. Calculate a decimal approximation straightforwardly, convert
    it back to binary to see if there's a discrepancy, and use the
    discrepancy to adjust approximation until an exact solution is found.

    I m pretty certain, but you need a formal proof, and there is a margin
    e.g. 34 +1 needed.

    Yeah for something like this it would be reassuring to have proofs.
    binary32 can be verified by exhaustive testing but not binary64.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Paul Rubin@no.email@nospam.invalid to comp.lang.forth on Wed Sep 30 09:39:53 2026
    From Newsgroup: comp.lang.forth

    dxf <dxforth@gmail.com> writes:
    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'.

    If you ask for 1/3 displayed to 30 places, that will also be wrong after
    the 17th or so place. What does your implementation do about this?
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From marcel hendrix@mhx@iae.nl to comp.lang.forth on Wed Sep 30 18:49:33 2026
    From Newsgroup: comp.lang.forth

    On 30/09/2026 3:44 pm, peter wrote:
    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!

    Yes, and I imagine x87 comes close without any additional resource. It's on account of IEEE's requirements that Intel used 80-bits internally.
    Programmers
    would go on to exploit it, saying 'what the heck, I'll just use 80 bits and forget about IEEE'. But with x87 deprecated, users are increasingly
    forced to
    use IEEE. The empire strikes back.

    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'.

    interesting is of course if you apply some function to that pi
    approximation

    3.141592653589793e0 fsin fs. 1.224646799147353e-16
    [..]

    ( 80-bit extended float)
    FORTH> 3.141592653589793e0 fsin +e. 1.2246063538223772168e-0016 ok

    ( 106-bit double-double )
    FORTH> dd=pi ddsin ddfe. 0e0 ok
    FORTH> dd=pi ddcos ddfe. -1.0000000000000000000000000000000e0 ok
    FORTH> dd=pi/2 ddcos ddfe. 0e0 ok
    FORTH> dd=pi/2 ddsin ddfe. 1.0000000000000000000000000000000e0 ok
    FORTH> dd=pi/4 ddsin ddfe. 7.0710678118654752440084436210482e-1 ok
    FORTH> dd=pi/4 ddcos ddfe. 7.0710678118654752440084436210482e-1 ok

    ( 128-bit extended double-double [yes, found the bug] )
    FORTH> xd=pi xdsin xdfe. -4.7019774032891500318749461488889827112e-38 ok FORTH> xd=pi xdcos xdfe. -1.0000000000000000000000000000000000000e0 ok FORTH> xd=pi/2 xdcos xdfe. 0e0 ok
    FORTH> xd=pi/2 xdsin xdfe. 1.0000000000000000000000000000000000000e0 ok FORTH> xd=pi/4 xdsin xdfe. 7.0710678118654752440084436210484903928e-1 ok FORTH> xd=pi/4 xdcos xdfe. 7.0710678118654752440084436210484903929e-1 ok FORTH> s" -4.7019774032891500318749461488889827112e-38" >XD xdfe.
    -4.7019774032891500318749461488889827112e-38 ok
    FORTH> s" -4.7019774032891500318749461488889827112e-38" >DD xdfe.
    -4.7019774032891500318749461488887361922e-38 ok

    -marcel
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From anton@anton@mips.complang.tuwien.ac.at (Anton Ertl) to comp.lang.forth on Wed Sep 30 16:42:41 2026
    From Newsgroup: comp.lang.forth

    peter <peter.noreply@tin.it> writes:
    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

    sin() only is zero at multiples of pi, sinpi() (a C23 function) at
    multiples of 1. Multiples of 1 are representable exactly up to 2^53 (9007199254740992) in binary64. So sinpi() does not have this problem
    up to quite-large operands.

    For cospi(x) it's similar, except that the x with 0 result value have
    the form x=n+0.5, where n is an integer. These numbers are
    representable exactly up to 2^52.

    For input values where the expected result is not 0 a small absolute
    error coming from the discretization of FP does not result in a huge
    relative error. But note that the discretization gets worse the
    bigger the FP number is.

    - anton
    --
    M. Anton Ertl http://www.complang.tuwien.ac.at/anton/home.html
    comp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html
    New standard: https://forth-standard.org/
    EuroForth 2026 CFP: http://www.euroforth.org/ef26/cfp.html
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From marcel hendrix@mhx@iae.nl to comp.lang.forth on Wed Sep 30 19:06:49 2026
    From Newsgroup: comp.lang.forth

    On 9/30/2026 6:49 PM, marcel hendrix wrote:
    [..]> FORTH> s" -4.7019774032891500318749461488889827112e-38" >DD xdfe.
    -a-a-a-a-a-a-a-a-a -4.7019774032891500318749461488887361922e-38-a ok
    My bad. Note that ">DD" should have been ">XD" :
    FORTH> s" -4.7019774032891500318749461488889827112e-38" >DD ddfe.
    -4.7019774032891500318749461488887e-38 ok

    -marcel
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Krishna Myneni@krishna.myneni@ccreweb.org to comp.lang.forth on Wed Sep 30 15:25:42 2026
    From Newsgroup: comp.lang.forth

    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 ===


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From anton@anton@mips.complang.tuwien.ac.at (Anton Ertl) to comp.lang.forth on Wed Sep 30 20:54:55 2026
    From Newsgroup: comp.lang.forth

    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 with 17 digits you are guarenteed to be able to differentiate
    between one FP value and the next or previous one, and therefore you
    are guaranteed to be able to convert back to the original FP value.

    It looks like getting the right 17 digit
    approximation is very complicated.

    If you try to do it efficiently, it certainly is.

    - anton
    --
    M. Anton Ertl http://www.complang.tuwien.ac.at/anton/home.html
    comp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html
    New standard: https://forth-standard.org/
    EuroForth 2026 CFP: http://www.euroforth.org/ef26/cfp.html
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From peter@peter.noreply@tin.it to comp.lang.forth on Wed Sep 30 23:52:28 2026
    From Newsgroup: comp.lang.forth

    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.

    BR
    Peter


    === 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 ===




    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Krishna Myneni@krishna.myneni@ccreweb.org to comp.lang.forth on Wed Sep 30 17:49:05 2026
    From Newsgroup: comp.lang.forth

    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

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Krishna Myneni@krishna.myneni@ccreweb.org to comp.lang.forth on Wed Sep 30 18:50:09 2026
    From Newsgroup: comp.lang.forth

    On 9/30/26 5:49 PM, Krishna Myneni wrote:
    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.
    ...

    Ok. I understand what is happening now, and I agree it is a bug in my implementation of REPRESENT, which should not write more characters into
    the buffer than requested. Will fix this presently.

    --
    Krishna


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From dxf@dxforth@gmail.com to comp.lang.forth on Thu Oct 1 12:09:42 2026
    From Newsgroup: comp.lang.forth

    On 1/10/2026 1:42 am, peter wrote:
    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.


    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.

    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.

    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!

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From anton@anton@mips.complang.tuwien.ac.at (Anton Ertl) to comp.lang.forth on Thu Oct 1 06:02:10 2026
    From Newsgroup: comp.lang.forth

    anton@mips.complang.tuwien.ac.at (Anton Ertl) writes:
    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.

    Actually 2.22e-16. And given that there is a leading digit >=1e in
    1e, this means we can use 17 digits to differentiate between 1e and 1e
    fnext, but 16 digits would be too few.

    For cases where the first digit of the
    decimal representation is >2e, 1 ulp is even larger.

    Let's also look at the other powers of 10. Why those? Because the
    ulp for 9.99e... is (8 or 16 times) bigger than the ulp for 1e..., so
    if the ulp is big enough for 1e..., it is also big enough for other
    numbers with the same decimal exponent.

    : fnext ( r1 -- r2 )
    {: f^ x :} x @ 1+ x ! x f@ ;

    : ulp ( r1 -- r2 )
    fdup fnext fswap f- ;

    : relative-ulp ( r1 -- r2 )
    fdup ulp fswap f/ ;

    \ note that the relative ulp for 9.99eX is not the difference between
    \ the last digits in the decimal representation, but the relative ulp
    \ for 1eX is.

    : fmin ( r1 r2 -- r )
    fover fover f> if fswap then fdrop ;

    : fmax ( r1 r2 -- r )
    fover fover f< if fswap then fdrop ;

    : differences ( nlimit nstart -- )
    1e 0e ?do ( rmin rmax )
    cr i 4 .r space
    10e i s>f f** relative-ulp fdup e.
    frot fover fmin
    f-rot fmax
    loop
    cr ." max relative ulp: " e.
    cr ." min relative ulp: " e. ;

    \ what if the result of F** is 9.999...e(i-1)? That is no problem,
    \ because relative-ulp is normally very close to what it would be for a
    \ slightly bigger number. The only differences occur for the previous
    \ FP number of a number with binary mantissa 1, i.e., the previous FP
    \ number of a power of two, but numbers with decimal mantissa 1 do not
    \ look like that, at least for the usual exponent ranges.

    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 minimum is relevant for the question how many digits we need at
    the most for being able to convert back. Given that it is >=1e-16, 17
    decimal digits are enough to know that a number is different from the
    next FP number, in the worst case (i.e., decimal mantissa slightly
    above 1, and the worst of the exponents available).

    If you use a higher nlimit, the exponent goes out of range for
    binary64; if you use a smaller nstart, you get into the denormal
    numbers, where the ulps become bigger and you need fewer digits to differentiate between them (only one for 0e fnext):

    -307 -323 differences
    -323 .5e
    -322 .05e
    -321 .0049504950495049506e
    -320 .0004940711462450593e
    -319 .00004940711462450593e
    -318 4.940662641673502e-6
    -317 4.940655318640154e-7
    -316 4.940656539144204e-8
    -315 4.940656465913944e-9
    -314 4.940656458590919e-10
    -313 4.9406564583468176e-11
    -312 4.940656458420048e-12
    -311 4.940656458412725e-13
    -310 4.9406564584124806e-14
    -309 4.940656458412456e-15
    -308 4.9406564584124655e-16
    max relative ulp:.5e
    min relative ulp:4.9406564584124655e-16 ok

    The output for "30 0 differences" is interesting:

    30 0 differences
    0 2.220446049250313e-16
    1 1.7763568394002506e-16
    2 1.4210854715202004e-16
    3 1.1368683772161603e-16
    4 1.8189894035458566e-16
    5 1.4551915228366853e-16
    6 1.164153218269348e-16
    7 1.862645149230957e-16
    8 1.4901161193847657e-16
    9 1.1920928955078126e-16
    10 1.9073486328125e-16
    11 1.52587890625e-16
    12 1.220703125e-16
    13 1.953125e-16
    14 1.5625e-16
    15 1.25e-16
    16 2e-16
    17 1.6e-16
    18 1.28e-16
    19 2.048e-16
    20 1.6384e-16
    21 1.31072e-16
    22 2.097152e-16
    23 1.6777216e-16
    24 1.3421772800000001e-16
    25 2.1474836479999998e-16
    26 1.7179869183999998e-16
    27 1.37438953472e-16
    28 2.1990232555520002e-16
    29 1.7592186044416001e-16

    So "1e16 fnext" is 10000000000000002e. That's because the range of
    integers where all integers can be represented ends at 2^53, i.e., 9007199254740992e. Putting them in one column:

    9007199254740992e
    10000000000000002e

    10000000000000001e cannot be represented as binary64 number, because
    it would require an additional bit in the binary mantissa.

    - anton
    --
    M. Anton Ertl http://www.complang.tuwien.ac.at/anton/home.html
    comp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html
    New standard: https://forth-standard.org/
    EuroForth 2026 CFP: http://www.euroforth.org/ef26/cfp.html
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Paul Rubin@no.email@nospam.invalid to comp.lang.forth on Thu Oct 1 00:04:03 2026
    From Newsgroup: comp.lang.forth

    anton@mips.complang.tuwien.ac.at (Anton Ertl) writes:
    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.

    Yes, alternatively you can notice that 2**53 is about 9e15, so there are
    ~10x as many 17 digit decimal strings as 53 bit binary mantissas, which
    at least gives hope. But a real proof requires chasing down a lot more details, edge cases, etc. You want further than I did, in actually
    checking the layout of bits in the binary64.

    I'd be interested in having a formally verified ftoa someday, maybe in
    Ada which has some real formalization tools and also has a usable C
    interface. I don't have much clue about how to actually pursue writing
    one though.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Paul Rubin@no.email@nospam.invalid to comp.lang.forth on Thu Oct 1 00:05:50 2026
    From Newsgroup: comp.lang.forth

    Lars Brinkhoff <lars.spam@nocrew.org> writes:
    "How to print floating-point numbers accurately"
    Guy L. Steele, Jr., Jon L. White

    Thanks, I think I've seen this paper or citations to it before, but
    haven't actually read it. I'll try to do so.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From anton@anton@mips.complang.tuwien.ac.at (Anton Ertl) to comp.lang.forth on Thu Oct 1 07:26:19 2026
    From Newsgroup: comp.lang.forth

    anton@mips.complang.tuwien.ac.at (Anton Ertl) writes:
    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.

    And what you also may notice:

    9007199254740992e 1.1113793747425387e-16 f* e.

    gives

    1.0010415475915504e

    Or, conversely, the minimum relative ulp for numbers with 53-bit
    binary mantissae is 2^-53, i.e., 1.1102230246251565e-16, which is
    =1e-16, so 17 decimal digits are enough to represent the binary
    mantissa, even if you combine that with huge exponents.

    - anton
    --
    M. Anton Ertl http://www.complang.tuwien.ac.at/anton/home.html
    comp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html
    New standard: https://forth-standard.org/
    EuroForth 2026 CFP: http://www.euroforth.org/ef26/cfp.html
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Paul Rubin@no.email@nospam.invalid to comp.lang.forth on Thu Oct 1 00:43:32 2026
    From Newsgroup: comp.lang.forth

    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.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From anton@anton@mips.complang.tuwien.ac.at (Anton Ertl) to comp.lang.forth on Thu Oct 1 07:55:52 2026
    From Newsgroup: comp.lang.forth

    Paul Rubin <no.email@nospam.invalid> writes:
    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.

    A simple version of converting r to decimal would be:

    Special-case 0, infinities and NaN.

    Start with the minimum representable positive number in decimal
    representation, a number with 751 decimal digits of mantissa for
    binary64.

    Double the number until you reach the exponent of the least
    significant bit of r.

    Now multiply with the mantissa of r (including the hidden bit for
    normal numbers). You can do that by doubling and adding, for each 1
    present.

    Now you have the full length of the mantissa; append zeros if it is
    too short for the requested digits. If it is too long for the
    requested digits, round it: if the digits following the desired part
    are >50...0, round up; if the are <50..0, round down, and if they are
    =50..0, round the last desired digit to even.

    The exponent is now based on where the most significant digit of the
    result is.

    - anton
    --
    M. Anton Ertl http://www.complang.tuwien.ac.at/anton/home.html
    comp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html
    New standard: https://forth-standard.org/
    EuroForth 2026 CFP: http://www.euroforth.org/ef26/cfp.html
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Paul Rubin@no.email@nospam.invalid to comp.lang.forth on Thu Oct 1 01:37:54 2026
    From Newsgroup: comp.lang.forth

    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. Also, showing that binary->decimal->binary = identity requires including the decimal-to-binary (atof) algorithm in the
    analysis as well as ftoa. The Steele and White article about printing
    flonums (Lisp jargon for floating point numbers) was accompanied by a
    separate article by Clinger about reading them.

    Finallly, this approach is even less practical for float128, which has
    15 exponent bits instead of 11. I would have hoped that multi-precision
    was never needed, or maybe only occasionally needed, and never more than
    a few extra digits.

    I think even specifying this problem precisely would be a huge mess.
    The specification would encompass most of the details of the IEEE FP
    numeric representations.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From anton@anton@mips.complang.tuwien.ac.at (Anton Ertl) to comp.lang.forth on Thu Oct 1 08:46:15 2026
    From Newsgroup: comp.lang.forth

    Paul Rubin <no.email@nospam.invalid> writes:
    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.

    Maybe not what you have in mind, but the only things that you need as
    basis for all of this is a word that can perform decimal addition of ~1400-digit numbers (only fixed-size fixed-point numbers for
    simplicity's sake), and a way to find the most significant non-zero
    digit. Both are pretty straightforward to implement.

    And of course this approach is outrageously expensive, especially, as
    you note, with larger exponent ranges in the FP numbers. Then you
    look in the literature listed on the last page of <http://www.complang.tuwien.ac.at/Bachelorarbeiten/orlov23.pdf> and
    look for where they are in the complexity vs. efficiency balance.

    Concerning the other direction, I expect that there is a similar
    complexity vs. efficiency balance there.

    - anton
    --
    M. Anton Ertl http://www.complang.tuwien.ac.at/anton/home.html
    comp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html
    New standard: https://forth-standard.org/
    EuroForth 2026 CFP: http://www.euroforth.org/ef26/cfp.html
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From peter@peter.noreply@tin.it to comp.lang.forth on Thu Oct 1 11:04:31 2026
    From Newsgroup: comp.lang.forth

    On Wed, 30 Sep 2026 17:49:05 -0500
    Krishna Myneni <krishna.myneni@ccreweb.org> wrote:

    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 use a newly compiled kForth64 running kforth64-fast and get this

    123e45 0 0 represent
    Segmentation fault (core dumped) peter@R9950WSL:/mnt/d/dev/forth/kForth-64-0.8.4$

    When I retest with kforth64 I get the same result as you have!

    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?

    If you give the buffer lenght as 0, nothing should be written!

    BR
    Peter

    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



    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From peter@peter.noreply@tin.it to comp.lang.forth on Thu Oct 1 11:13:45 2026
    From Newsgroup: comp.lang.forth

    On Thu, 1 Oct 2026 12:09:42 +1000
    dxf <dxforth@gmail.com> wrote:
    On 1/10/2026 1:42 am, peter wrote:
    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.


    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.

    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.

    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
    I get
    1 set-precision ok
    1e 0e f/ 0 f.n Inf ok
    I use the host system F. when I detect a 0 flag from represent
    So it prints whatever that F. does. It is a bit unclear what
    decimal places should do for a text string!
    On my system the negative n does just reduce the number of
    significant digits asked from represent so it should round
    correctly. there is a test to limit negative n to -(exp-1)
    BR
    Peter

    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!

    --- Synchronet 3.22a-Linux NewsLink 1.2