On Fri, Apr 9, 2021 at 10:26 AM Ralph Mellor <ralphdjmel...@gmail.com>
wrote:

> Another thing I've bumped into in my travels:
>
> > From: Zefram
> > Sent: Thursday, February 18, 2016 4:08 AM
> > To: perl5-port...@perl.org
> > Subject: Re: [perl #127182] One digit short to correctly stringify a
> double
>
> >> To have different NVs stringify identically is surprising; to have the
> >> closest approximation to 0.1 stringify other than "0.1" is also
> >> surprising; so I think Steele's rule specifically achieves least
> surprise
> >> here.
>
> > I keep forgetting that perl has a thing about minimising surprises - and
> > that's probably a good enough reason for perl to abide by Steele's rule.
> > So I'll now accept that I can live with that :-)
>
> > The hex form of 0.1 is 0x1.999999999999ap-4, and whenever that double is
> > printed, I gather Steele's rule will decree that it be printed out as
> > '0.1' - irrespective of whether that double was derived as 1/10 or
> > 10000000000000001/1e17.
> > But there's nothing to object about in that, AFAICS.
>
> > Anyway, as I've already noted, one can always resort to printf if need
> be.
>
> Remember that? Am I right in thinking that your view remains
> that you can live with the above?
>

As regards that particular anomaly ? ... "Yes and No" ;-).
My answer is "Yes", in that perl5 still does not adhere to what Zefram
termed "Steele's principle", and I continue to tolerate that on a daily
basis.
In its simplest form, "Steeles's principle" is (wrt both the raku and perl
notation) the condition that  $num == "$num" should always be true (unless
$num is NaN) && "$num" should consist of as few digits as possible.

Perl often fails to meet this condition:
C:\>perl -le "my $d = sqrt 2; print 'wtf' if $d != \"$d\""
wtf

But, thanks to Zoffix's implementation of grisu3, raku does meet this
condition:

C:\>raku -e "my $d = sqrt 2; say 'ok' if $d =\"$d\""
ok

It's also courtesy of grisu3 that the 2nd part of the condition is met.
Otherwise:

C:\>raku -e "say 0.1e0"
0.1

would instead output 0.10000000000000001.

With raku, it's not alway the case that the second part of the condition is
met.
If grisu3 fails to provide a result (as can happen for a small number of
values) then "say()" falls back to "%.17g" formatting.
There are therefore in fact a number of values that raku represents using
17 significant digits when fewer than 17 digits are required. (This is not
a great shortcoming IMO.)

My answer is "No" in that, in my Math::MPFR (perl5) module, I've
implemented doubletoa() which is grisu3 under the hood.
I've also implemented, in the same Module, a function I've called nvtoa()
which draws on the directions specified on p120 of  "How to Print
Floating-Point Numbers Accurately" by Guy L. Steele Jr and Jon L. White.
It also meets "Steele's principle" - which is not surprising as it's the
paper that presents "Steele's principle".
This is not as efficient as grisu3, but as well as working with doubles, it
also works with long doubles, __float128s and IBM double-doubles.
I've implemented this functionality for the purpose of working around the
inadequacy in perl5.


>
> That all sounds good to me, though there can be different dimensions
> of surprise, and it may be that Raku's take on having different Nums
> stringify identically is different from Zefram's/Steele's/your formulation.
>
>
I believe Raku will always have different Nums (ie doubles) stringify
differently.
Do you have an example to the contrary  ?
AFAIK, it's only perl that will happily stringify different Nums (NVs)
identically.

One thing I'm unclear on as yet is whether Raku has the same or a
> different position than the above in principle, modulo bugs / weakness
> in the current sprintf implementation.
>
>
I think that when "sprintf '%.17g', 0f.1e0" returns 0.1, then the
conditions laid out by C89, C99 and C11 are not being met.
However C99 and C11 seem to allow that it is not mandatory to output more
than 17 digits (for double precision values).

I'm happy to elaborate on any of this if needed.

Cheers,
Rob

Reply via email to