zsh-workers
 help / color / mirror / code / Atom feed
From: Roman Perepelitsa <roman.perepelitsa@gmail.com>
To: Zsh hackers list <zsh-workers@zsh.org>
Subject: Re: zsh converts a floating-point number to string with too much precision
Date: Sat, 21 Dec 2019 10:43:43 +0100	[thread overview]
Message-ID: <CAN=4vMrgHmo6QRejar1kWMJgFH60m3LvCn4-SkK7Mk1GrSE_YA@mail.gmail.com> (raw)
In-Reply-To: <20191221084736.bokldw7tzxw3thn3@chaz.gmail.com>

On Sat, Dec 21, 2019 at 9:48 AM Stephane Chazelas
<stephane.chazelas@gmail.com> wrote:
> So on a system (with a compiler) where C doubles are implemented
> as IEEE 754 double precision, both 1.1 and 1.1000000000000001
> are represented as the same binary double (whose exact value is
> 1.100000000000000088817841970012523233890533447265625).
>
> So you're saying echo $((1.1000000000000001)) and echo $((1.1))
> should output 1.1, because even though 1.1000000000000001 is
> closer to that value than 1.1000000000000000, zsh should pick
> the latter because people prefer to see shorter number
> representations and in that case it doesn't matter which one we
> pick as both lead to the same double.

Correct. The best formal description of this process that I know of is
the specification of to_chars() functions in the C++ standard:

    The functions [...] ensure that the string representation consists
    of the smallest number of characters such that there is at least
    one digit before the radix point (if present) and parsing the
    representation using the corresponding from_chars function
    recovers value exactly. [Note: This guarantee applies only if
    to_chars and from_chars are executed on the same implementation.
    — end note] If there are several such representations, the
    representation with the smallest difference from the
    floating-point argument value is chosen, resolving any remaining
    ties using rounding according to round_to_nearest.

There is no simple algorithm that achieves this. I recall reading long
papers a few years back that were describing various inventions in
this field. They were pretty scary.

> Is there a standard C API for that?

Not that I know of. FWIW, neither gcc (libstdc++) nor clang (libc++)
have implemented to_chars() for floating points in the two years since
it's been added to the standard (C++17).

>
> Or would we get the output of sprintf("%.17g"), look at the last
> two significant digits, if the second last is 9 or 0, then see
> if rounding it and doing a strtod again yields the same double?

I believe printing the value with full precision and then truncating
the string this is the most popular approach. All implementations that
are faster are only marginally so, and they are much more complex. I
think this approach should work well enough for zsh. Lifting this sort
of implementation from another project would be ideal (someone would
have to find it; my apologies for not doing it myself).

Roman.

  reply	other threads:[~2019-12-21  9:44 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-12-20  1:37 Vincent Lefevre
2019-12-20  3:38 ` Mikael Magnusson
2019-12-20 16:58 ` Stephane Chazelas
2019-12-20 17:12   ` Roman Perepelitsa
2019-12-21  0:50     ` Vincent Lefevre
2019-12-21  8:47       ` Stephane Chazelas
2019-12-21  9:43         ` Roman Perepelitsa [this message]
2019-12-21 17:56           ` Stephane Chazelas
2019-12-21 18:11             ` Stephane Chazelas
2019-12-21 18:20               ` Roman Perepelitsa
2019-12-21 21:28         ` Vincent Lefevre
2019-12-21  1:00   ` Vincent Lefevre

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAN=4vMrgHmo6QRejar1kWMJgFH60m3LvCn4-SkK7Mk1GrSE_YA@mail.gmail.com' \
    --to=roman.perepelitsa@gmail.com \
    --cc=zsh-workers@zsh.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).