-
Notifications
You must be signed in to change notification settings - Fork 552
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
One digit short to correctly stringify a double #15119
Comments
From dankogai@dan.co.jpCreated by dankogai@cpan.orgAccording to: http://stackoverflow.com/questions/4738768/printing-double-without-losing-precision we need 16 decimal digits to restore a double. But Perl as of 5.22.1 gives us only 15. % perl -E 'say log(2)' As a result, we get: % perl -E 'say 0+(log(2)==0.693147180559945)' FYI here's what other platforms give: Go -- OK Though we should not use decimal notations to exchange doubles (and we have hexfloat support since 5.22), we can hardly avoid that with JSON is so ubiquitous and all numbers are doubles therein. Dan the Bit-Picking Perl Monger Perl Info
|
From dankogai@dan.co.jpSeems like the simplest solution is just sprintf "%.17g". Perl (and Swift) appears to be using the equivalent of sprintf "%.16g", which is one digit short. C http://ideone.com/5Dq4ip Dan the Bug Reporter On Wed Jan 06 03:24:54 2016, dankogai wrote:
|
From [Unknown Contact. See original ticket]Seems like the simplest solution is just sprintf "%.17g". Perl (and Swift) appears to be using the equivalent of sprintf "%.16g", which is one digit short. C http://ideone.com/5Dq4ip Dan the Bug Reporter On Wed Jan 06 03:24:54 2016, dankogai wrote:
|
From @craigberryOn Wed, Jan 6, 2016 at 5:24 AM, Dan Kogai <perlbug-followup@perl.org> wrote:
A lossless round trip to character and back takes 17 digits, at least <https://en.wikipedia.org/wiki/Double-precision_floating-point_format> And changing 16 to 17 fixed a loss of precision problem I was having <http://lists.ibiblio.org/pipermail/freetds/2014q3/029003.html> |
The RT System itself - Status changed from 'new' to 'open' |
From zefram@fysh.orgCraig A. Berry wrote:
and also requires fixing [perl #41202]. -zefram |
From @sisyphusOn Wed Jan 06 14:17:56 2016, craig.a.berry@gmail.com wrote:
Similarly we find that long double and __float128 NVs are also a few bits short of satisfying the condition being considered here. The number of decimal digits required is given by the expression 1+ceil(P*log(2)/log(10)), where P is the precision (in bits) of the NV. Currently we get 15 (DBL_DIG), 18 (LDBL_DIG), 30 (LDBL_DIG - 1) and 32 (FLT128_DIG - 1) decimal digits (respectively). Cheers, |
From @sisyphusOn Sun Feb 07 18:57:42 2016, sisyphus wrote:
Groan ... I did say "a few bits short", but I meant, of course, "a few decimal digits short". Cheers, |
From @jhiI quickly tried adding the number of decimal digits in the default stringification, as suggested by Sisyphus, and one thing that immediately fails is the "classic" illusion that 0.1 stringifies as "0.1". And t/base/num.t tests for that, and other similar illusions. Whether it is right to be testing such, is of course another matter. I think it's quite dubious, anyway, given how tricksy the binary<->decimal conversion are. FWIW, I seem to have been part of the dubiousness: http://perl5.git.perl.org/perl.git/commit/925fa5a876ae65e605ff8becef8ac0c232c8148f?f=t/base/num.t I temporarily bypassed those failing t/base tests, and the following still fail in "make minitest": Failed 4 tests out of 327, 98.78% okay. (details below) I'll work through those (probably just similarly bypassing them for now) and see how the full "make test" goes. One thing I know will be all fireworks is Math::Complex which assumes a certain number of fractional digits. Failure details: t/base/num.t: not ok 5 # 0.10000000000000001 t/op/hexfp.t: # Failed test 95 - at t/op/hexfp.t line 214 t/op/override.t: # Failed test 6 - at t/op/override.t line 43 t/op/pack.t: # Failed test 13177 - at t/op/pack.t line 1418 t/op/tie.t: not ok 18 # TODO IO "self-tie" via TEMP glob |
From @jhiSome further results. TL;DR: This may be a too deep a pool to wade in this close to 5.24. I think the best technical summary is: ./perl -wle 'print .1' Find attached: With these, "make minitest" passes for me in OS X with default settings (boring 64-bit IEEE 754, x86_64). Also find attached: One thing that kills many of the full test ones is that the v-string stringification goes bang. |
From @jhi0001-Introduce-NV_DEC_DIG.patchFrom bda66201bbfde3169e888ff26cafa7bb8ba028b2 Mon Sep 17 00:00:00 2001
From: Jarkko Hietaniemi <jhi@iki.fi>
Date: Sat, 13 Feb 2016 16:22:35 -0500
Subject: [PATCH 1/4] Introduce NV_DEC_DIG.
NV_DEC_DIG is like NV_DIG (number of digits for decimal floating)
but usually 1-3 more.
---
perl.h | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/perl.h b/perl.h
index a2ba5cd..050f25e 100644
--- a/perl.h
+++ b/perl.h
@@ -2065,6 +2065,25 @@ extern long double Perl_my_frexpl(long double x, int *e);
# endif
# endif
+/* NV_DEC_DIG is the number of decimal digits required to print
+ * NV_MANT_DIG bits of precision in decimal, without loss of
+ * precision. This is usually 1-3 more digits than NV_DIG.
+ * We have precomputed values for the most common cases,
+ * and generic formula for the rest. */
+#ifndef NV_DEC_DIG
+# if NV_MANT_DIG == 53 /* IEEE 754 64-bit double */
+# define NV_DEC_DIG 17
+# elif NV_MANT_DIG == 64 /* x86 80-bit extended precision */
+# define NV_DEC_DIG 21
+# elif (NV_MANT_DIG == 106 || NV_MANT_DIG == 107) /* double-double */
+# define NV_DEC_DIG 33
+# elif NV_MANT_DIG == 113 /* IEEE 754 128-bit double */
+# define NV_DEC_DIG 36
+# else
+# defined NV_DEC_DIG (1+Perl_ceil(NV_MANT_DIG*log(2)/log(10)))
+# endif
+#endif
+
/* These math interfaces are C89. */
# define Perl_acos acos
# define Perl_asin asin
--
2.7.0
|
From @jhi0002-Use-the-new-NV_DEC_DIG.patchFrom 76b74fccf5d7779bd79305c9889bcb35f6ec59c0 Mon Sep 17 00:00:00 2001
From: Jarkko Hietaniemi <jhi@iki.fi>
Date: Sat, 13 Feb 2016 16:50:59 -0500
Subject: [PATCH 2/4] Use the new NV_DEC_DIG
---
dump.c | 2 +-
sv.c | 12 ++++++------
2 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/dump.c b/dump.c
index bc2776a..cbe64b8 100644
--- a/dump.c
+++ b/dump.c
@@ -1567,7 +1567,7 @@ Perl_do_sv_dump(pTHX_ I32 level, PerlIO *file, SV *sv, I32 nest, I32 maxnest, bo
&& type != SVt_PVIO && !isGV_with_GP(sv) && !SvVALID(sv))
|| type == SVt_NV) {
STORE_LC_NUMERIC_UNDERLYING_SET_STANDARD();
- Perl_dump_indent(aTHX_ level, file, " NV = %.*" NVgf "\n", NV_DIG, SvNVX(sv));
+ Perl_dump_indent(aTHX_ level, file, " NV = %.*" NVgf "\n", NV_DEC_DIG, SvNVX(sv));
RESTORE_LC_NUMERIC_UNDERLYING();
}
diff --git a/sv.c b/sv.c
index 819a250..fc04137 100644
--- a/sv.c
+++ b/sv.c
@@ -3103,7 +3103,7 @@ Perl_sv_2pv_flags(pTHX_ SV *const sv, STRLEN *const lp, const I32 flags)
size =
1 + /* sign */
1 + /* "." */
- NV_DIG +
+ NV_DEC_DIG +
1 + /* "e" */
1 + /* sign */
5 + /* exponent digits */
@@ -3112,7 +3112,7 @@ Perl_sv_2pv_flags(pTHX_ SV *const sv, STRLEN *const lp, const I32 flags)
s = SvGROW_mutable(sv, size);
#ifndef USE_LOCALE_NUMERIC
- SNPRINTF_G(SvNVX(sv), s, SvLEN(sv), NV_DIG);
+ SNPRINTF_G(SvNVX(sv), s, SvLEN(sv), NV_DEC_DIG);
SvPOK_on(sv);
#else
@@ -3127,7 +3127,7 @@ Perl_sv_2pv_flags(pTHX_ SV *const sv, STRLEN *const lp, const I32 flags)
s = SvGROW_mutable(sv, size);
}
- SNPRINTF_G(SvNVX(sv), s, SvLEN(sv), NV_DIG);
+ SNPRINTF_G(SvNVX(sv), s, SvLEN(sv), NV_DEC_DIG);
/* If the radix character is UTF-8, and actually is in the
* output, turn on the UTF-8 flag for the scalar */
@@ -11295,9 +11295,9 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p
const bool pat_utf8 = has_utf8; /* the pattern is in utf8? */
SV *nsv = NULL;
/* Times 4: a decimal digit takes more than 3 binary digits.
- * NV_DIG: mantissa takes than many decimal digits.
+ * NV_DEC_DIG: mantissa takes than many decimal digits.
* Plus 32: Playing safe. */
- char ebuf[IV_DIG * 4 + NV_DIG + 32];
+ char ebuf[IV_DIG * 4 + NV_DEC_DIG + 32];
bool no_redundant_warning = FALSE; /* did we use any explicit format parameter index? */
bool hexfp = FALSE; /* hexadecimal floating point? */
@@ -11368,7 +11368,7 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p
/* Add check for digits != 0 because it seems that some
gconverts are buggy in this case, and we don't yet have
a Configure test for this. */
- if (digits && digits < sizeof(ebuf) - NV_DIG - 10) {
+ if (digits && digits < sizeof(ebuf) - NV_DEC_DIG - 10) {
/* 0, point, slack */
STORE_LC_NUMERIC_SET_TO_NEEDED();
SNPRINTF_G(nv, ebuf, size, digits);
--
2.7.0
|
From @jhi0003-No-.1-and-the-like-in-t-base-num.t.patchFrom 2f4f2a50230cd9278a201d9a0c09a3ed80c5f56e Mon Sep 17 00:00:00 2001
From: Jarkko Hietaniemi <jhi@iki.fi>
Date: Sun, 14 Feb 2016 10:59:16 -0500
Subject: [PATCH 3/4] No .1 and the like in t/base/num.t
Since 0.1 is a lie with IEEE 754.
---
t/base/num.t | 44 ++++++++++++++++++++++----------------------
1 file changed, 22 insertions(+), 22 deletions(-)
diff --git a/t/base/num.t b/t/base/num.t
index 8a61fb9..b138fbf 100644
--- a/t/base/num.t
+++ b/t/base/num.t
@@ -17,17 +17,17 @@ print $a eq "1" ? "ok 3\n" : "not ok 3 # $a\n";
$a = -1.; "$a";
print $a eq "-1" ? "ok 4\n" : "not ok 4 # $a\n";
-$a = 0.1; "$a";
-print $a eq "0.1" ? "ok 5\n" : "not ok 5 # $a\n";
+$a = 0.125; "$a"; # 1+1/8
+print $a eq "0.125" ? "ok 5\n" : "not ok 5 # $a\n";
-$a = -0.1; "$a";
-print $a eq "-0.1" ? "ok 6\n" : "not ok 6 # $a\n";
+$a = -0.125; "$a";
+print $a eq "-0.125" ? "ok 6\n" : "not ok 6 # $a\n";
-$a = .1; "$a";
-print $a eq "0.1" ? "ok 7\n" : "not ok 7 # $a\n";
+$a = .125; "$a";
+print $a eq "0.125" ? "ok 7\n" : "not ok 7 # $a\n";
-$a = -.1; "$a";
-print $a eq "-0.1" ? "ok 8\n" : "not ok 8 # $a\n";
+$a = -.125; "$a";
+print $a eq "-0.125" ? "ok 8\n" : "not ok 8 # $a\n";
$a = 10.01; "$a";
print $a eq "10.01" ? "ok 9\n" : "not ok 9 # $a\n";
@@ -131,26 +131,26 @@ if ($^O eq 'os2') { # In the long run, fix this. For 5.8.0, deal.
print $a eq "0.0001" ? "ok 33\n" : "not ok 33 # $a\n";
}
-$a = 0.00009; "$a";
-print $a eq "9e-05" || $a eq "9e-005" ? "ok 34\n" : "not ok 34 # $a\n";
+$a = 1/16384; "$a";
+print $a eq "6.103515625e-05" || $a eq "6.103515625e-005" ? "ok 34\n" : "not ok 34 # $a\n";
-$a = 1.1; "$a";
-print $a eq "1.1" ? "ok 35\n" : "not ok 35 # $a\n";
+$a = 1.125; "$a";
+print $a eq "1.125" ? "ok 35\n" : "not ok 35 # $a\n";
$a = 1.01; "$a";
print $a eq "1.01" ? "ok 36\n" : "not ok 36 # $a\n";
-$a = 1.001; "$a";
-print $a eq "1.001" ? "ok 37\n" : "not ok 37 # $a\n";
+$a = 1.0009765625; "$a"; # 1+1/1024
+print $a eq "1.0009765625" ? "ok 37\n" : "not ok 37 # $a\n";
-$a = 1.0001; "$a";
-print $a eq "1.0001" ? "ok 38\n" : "not ok 38 # $a\n";
+$a = 1.0001220703125; "$a"; # 1+1/8192
+print $a eq "1.0001220703125" ? "ok 38\n" : "not ok 38 # $a\n";
-$a = 1.00001; "$a";
-print $a eq "1.00001" ? "ok 39\n" : "not ok 39 # $a\n";
+$a = 1.0000152587890625; "$a"; # 1+1/65536
+print $a eq "1.0000152587890625" ? "ok 39\n" : "not ok 39 # $a\n";
-$a = 1.000001; "$a";
-print $a eq "1.000001" ? "ok 40\n" : "not ok 40 # $a\n";
+$a = 1.0000009536743164; "$a"; # 1+1/1048576
+print $a eq "1.0000009536743164" ? "ok 40\n" : "not ok 40 # $a\n";
$a = 0.; "$a";
print $a eq "0" ? "ok 41\n" : "not ok 41 # $a\n";
@@ -164,9 +164,9 @@ print $a eq "-100000" ? "ok 43\n" : "not ok 43 # $a\n";
$a = 123.456; "$a";
print $a eq "123.456" ? "ok 44\n" : "not ok 44 # $a\n";
-$a = 1e34; "$a";
+$a = 1e30; "$a";
unless ($^O eq 'posix-bc')
-{ print $a eq "1e+34" || $a eq "1e+034" ? "ok 45\n" : "not ok 45 # $a\n"; }
+{ print $a eq "1e+30" || $a eq "1e+030" ? "ok 45\n" : "not ok 45 # $a\n"; }
else
{ print "ok 45 # skipped on $^O\n"; }
--
2.7.0
|
From @jhi0004-Binarily-exact-floats-handle-.5999-vs-.6000-diffs.patchFrom b0e300d922ebfb1569430e920e8d686d95157ba0 Mon Sep 17 00:00:00 2001
From: Jarkko Hietaniemi <jhi@iki.fi>
Date: Sun, 14 Feb 2016 11:36:51 -0500
Subject: [PATCH 4/4] Binarily exact floats, handle .5999 vs .6000 diffs.
---
t/op/hexfp.t | 10 +++++-----
t/op/override.t | 9 +++++++--
t/op/pack.t | 14 ++++++++++----
t/op/tie.t | 4 ++--
4 files changed, 24 insertions(+), 13 deletions(-)
diff --git a/t/op/hexfp.t b/t/op/hexfp.t
index 4b2a96d..7d05f4f 100644
--- a/t/op/hexfp.t
+++ b/t/op/hexfp.t
@@ -211,27 +211,27 @@ SKIP:
undef $a;
eval '$a = 0xfffffffffffffp0'; # 52 bits.
is(get_warn(), undef);
- is($a, 4.5035996273705e+15);
+ is($a, 4503599627370495);
undef $a;
eval '$a = 0xfffffffffffff.8p0'; # 53 bits.
is(get_warn(), undef);
- is($a, 4.5035996273705e+15);
+ is($a, 4503599627370495.5);
undef $a;
eval '$a = 0xfffffffffffff.cp0'; # 54 bits.
like(get_warn(), qr/^Hexadecimal float: mantissa overflow/);
- is($a, 4.5035996273705e+15);
+ is($a, 4503599627370496);
undef $a;
eval '$a = 0xf.ffffffffffffp0'; # 52 bits.
is(get_warn(), undef);
- is($a, 16);
+ is($a, 15.999999999999996);
undef $a;
eval '$a = 0xf.ffffffffffff8p0'; # 53 bits.
is(get_warn(), undef);
- is($a, 16);
+ is($a, 15.999999999999998);
undef $a;
eval '$a = 0xf.ffffffffffffcp0'; # 54 bits.
diff --git a/t/op/override.t b/t/op/override.t
index e660311..ffee721 100644
--- a/t/op/override.t
+++ b/t/op/override.t
@@ -28,7 +28,10 @@ is( 45, time + 3 );
# require has special behaviour
#
my $r;
-BEGIN { *CORE::GLOBAL::require = sub { $r = shift; 1; } }
+sub drop_zero_tail {
+ $_[0] =~ s/(\.00\d)0{6,}\d/\1/;
+}
+BEGIN { *CORE::GLOBAL::require = sub { $r = shift; drop_zero_tail($r); 1; } }
require Foo;
is( $r, "Foo.pm" );
@@ -55,7 +58,9 @@ is( $r, join($dirsep, "Foo", "Bar.pm") );
my @r;
local *CORE::GLOBAL::require = sub { push @r, shift; 1; };
eval "use 5.006";
- like( " @r ", qr " 5\.006 " );
+ my $r = " @r ";
+ drop_zero_tail($r);
+ like( $r, qr " 5\.006 " );
}
{
diff --git a/t/op/pack.t b/t/op/pack.t
index a2da636..70c2777 100644
--- a/t/op/pack.t
+++ b/t/op/pack.t
@@ -1413,9 +1413,12 @@ is(scalar unpack('A /A /A Z20', '3004bcde'), 'bcde');
ok( length $p);
my @b = unpack "$t X[$t] $t", $p; # Extract, step back, extract again
is(scalar @b, 2 * scalar @a);
+ my $a = "@a @a";
$b = "@b";
- $b =~ s/(?:17000+|16999+)\d+(e-45) /17$1 /gi; # stringification is gamble
- is($b, "@a @a");
+ for ($a, $b) {
+ s/(?:170*|16999+)\d+(e-45) /17$1 /gi; # stringification is gamble
+ }
+ is($b, $a);
use warnings qw(NONFATAL all);;
my $warning;
@@ -1426,9 +1429,12 @@ is(scalar unpack('A /A /A Z20', '3004bcde'), 'bcde');
is($warning, undef);
is(scalar @b, scalar @a);
+ my $a = "@a";
$b = "@b";
- $b =~ s/(?:17000+|16999+)\d+(e-45) /17$1 /gi; # stringification is gamble
- is($b, "@a");
+ for ($a, $b) {
+ s/(?:17000+|16999+)\d+(e-45) /17$1 /gi; # stringification is gamble
+ }
+ is($b, $a);
}
is(length(pack("j", 0)), $Config{ivsize});
diff --git a/t/op/tie.t b/t/op/tie.t
index ae0db6f..51131e7 100644
--- a/t/op/tie.t
+++ b/t/op/tie.t
@@ -563,11 +563,11 @@ FIRSTKEY
empty
########
sub TIESCALAR { bless {} }
-sub FETCH { my $x = 3.3; 1 if 0+$x; $x }
+sub FETCH { my $x = 3.25; 1 if 0+$x; $x }
tie $h, "main";
print $h,"\n";
EXPECT
-3.3
+3.25
########
sub TIESCALAR { bless {} }
sub FETCH { shift()->{i} ++ }
--
2.7.0
|
From @jhi |
From @jhi |
From @sisyphus-----Original Message-----
Additionally: perl -wle 'print "ok" if 0.1 == 0.10000000000000001;' perl -wle 'print "ok" if 0.1 == 0.10000000000000000;' and: perl -wle 'print "ok" if sqrt 2.0 == 1.4142135623730951;' perl -wle 'print "ok" if sqrt 2.0 == 1.4142135623730952;' I'm in favour of this change (for 5.26) - it makes good sense to me (despite Cheers, |
From @epaThe original bug report contains examples of languages that stringify Both 0.1 and 0.10000000000000001 represent the same double: % perl -E '$x = 0.1; $y = 0.10000000000000001; say $x == $y' Should perl start with 16 d.p., and then if the resulting string does indeed With the current number of d.p. output by perl, are there any surprising cases -- |
From zefram@fysh.orgEd Avis wrote:
Probably outputting the minimum number of digits such that reading In our case, this heuristic runs into a complication due to the I think we should fix the bug. But pending that fix, we have to decide -zefram |
From @jhi
Please see https://rt-archive.perl.org/perl5/Ticket/Display.html?id=122482
|
From @epaI agree that #122482 looks worth fixing, and in an ideal world it might be This does mean that, with Perl's current parser, there would be floating point Anyway - what I really wanted to say was that the change to output 16 d.p. -- |
From @sisyphus-----Original Message-----
My main reason for disagreeing is that the mpfr C library outputs I do wonder if there's an option to pragmatise here ? One other (obvious but hitherto unmentioned) fact is that anyone who wants Cheers, |
From @jhiFWIW I updated https://rt-archive.perl.org/perl5/Ticket/Display.html?id=122482 with some new pointers to munch with your breakfast cereal. |
From @sisyphus-----Original Message-----
Is there a cross-platform solution proposed there ? I once thought that using C's strtod/strtold/strtoflt128 would be the way to On Windows, I found that mingw.org's gcc-4.7.0/runtime had a strtod() that Sadly, mingw-w64 also appear to be rather disinterested in doing anything I think my only problems with strtold have been on ppc64, gcc-4.6.3. Cheers, |
From zefram@fysh.orgsisyphus1@optusnet.com.au wrote:
No. Stringification is not meaningfully subject to lexical scoping,
Yes, that's fine for people with very specific needs for textual -zefram |
From @sisyphus-----Original Message-----
I keep forgetting that perl has a thing about minimising surprises - and The hex form of 0.1 is 0x1.999999999999ap-4, and whenever that double is Anyway, as I've already noted, one can always resort to printf if need be. Cheers, |
From @jhi
Yes, gdtoa is the widely used solution for this problem. The 'g'-dtoa handles long doubles of all kinds, while bare dtoa does not. As opposed to other languages' runtimes, Perl is blessed/cursed with being able to be configured/used with different doubles, so we would need much of the 'gdtoa'. Reminder: despite the name 'dtoa', it also does 'atod'. So not just printf/gconvert, but also strtod.
See http://netlib.org/
My ambivalency stems from a few things: At the moment I am actually thinking that a technically better plan of action would be to make the gdtoa into a standalone library (with all the enhancements/fixes made by various projects using the library), and then just make it possible for Perl to use the library (just like with quadmath). The major hurdle of this plan might be getting a good working relationship with David Gay, but he seems a bit hard/slow to connect with. (And the code is copyright Lucent, that might be another painful issue, even though the code as such has been widely used in open source projects.) And not to mention that there would be a considerable lead time before the library would be available anywhere. So shorter term dealing with the integration pain might be unavoidable.
|
From zefram@fysh.orgI wrote:
I got bored and looked it up myself: Steele, Jr., Guy L., and White, Jon L., "How to print floating-point https://lists.nongnu.org/archive/html/gcl-devel/2012-10/pdfkieTlklRzN.pdf There's also some interesting historical commentary in: Steele, Jr., Guy L., and White, Jon L., "How to print floating-point http://grouper.ieee.org/groups/754/email/pdfq3pavhBfih.pdf -zefram |
From @karenetheridgeI just ran into something similar with PAUSE, when attempting to index a version containing a double: andk/pause#203 Although I do not know if it is the same issue as I haven't yet determined what versions of perl and version.pm are running there. |
From cpan@zoffix.comOn Sat, 20 Feb 2016 08:21:38 -0800, zefram@fysh.org wrote:
FWIW, recently worked on the same issue in Perl 6 on MoarVM, figured I'd mention Grisu3 algo[^1] looks to be an update to the Dragon stuff in those papers. I made[^2] MoarVM to use Grisu3 with snprintf("%.17g") as fallback for the 0.5% of cases. So far the code works great, fixed a bunch of precision bugs, and made Perl 6's [1] https://goo.gl/cbvogg Cheers, |
From @sisyphusOn Sun, 25 Mar 2018 20:38:05 -0700, cpan@zoffix.com wrote:
Nice work - perl5 should have been doing the same since 10 years ago (at least). The https://goo.gl/cbvogg link is not turning up anything. Do you have an updated link for that ? I've been playing around with the approach taken by Steele and White. My nvtoa() function accommodates -Duselongdouble (80-bit, 128-bit and DoubleDouble) and -Dusequadmath builds, as well as the more usual 'double' builds. The mpfr library is currently only used for the DoubleDouble build - and complete removal of that mpfr library dependency is a TODO. On my 'double' and 'long double' builds "nvtoa($nv)" is currently taking about 3 times longer than perl5's sprintf("%.16e", $nv). That's good enough for my own uses, but it's not "Rolls Royce" category ;-) Cheers, |
Migrated from rt.perl.org#127182 (status was 'open')
Searchable as RT127182$
The text was updated successfully, but these errors were encountered: