Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

mismatch between Perl 5.6 and Perl 5.8 in printing high precision values.

2 views
Skip to first unread message

vivekan...@gmail.com

unread,
Apr 2, 2008, 6:21:45 AM4/2/08
to
printf("%.32g\n",0.99999999976716936);

Perl 5.6.1 output:
0.99999999976716936 --> GOOD

Perl 5.8.6 output:
0.99999999976716925 --> ERROR


Any reason for such mismatch ?
Please let me know how to avoid that or any alternative approach if
any.

Thanks
Vivek

RedGrittyBrick

unread,
Apr 2, 2008, 7:02:44 AM4/2/08
to

print Math::BigFloat->new("0.99999999976716936")->bstr();


--
RGB

Mirco Wahab

unread,
Apr 2, 2008, 7:18:42 AM4/2/08
to

This is in the interval from 1e-16 to 1e-15, which
is the accuracy of a IEEE 8 byte double in this
number range (52 bits for fraction). Seems to
be ok ==> 1 / (2^52).
The correct result (above) needs (imho) longer
than 8 byte doubles, like

perl -MMath::BigFloat -e'print Math::BigFloat->new("0.99999999976716936")->bstr()'


Regards

M.

sisyphus

unread,
Apr 2, 2008, 9:46:46 AM4/2/08
to
On Apr 2, 9:21 pm, vivekanand.n...@gmail.com wrote:
> printf("%.32g\n",0.99999999976716936);
>
> Perl 5.6.1 output:
> 0.99999999976716936  --> GOOD
>
> Perl 5.8.6 output:
> 0.99999999976716925  --> ERROR
>
> Any reason for such mismatch ?

I believe it's a bug in perl 5.8 (which has been carried through to
perl 5.10):

C:\_32\pscrpt>perl -e "printf(\"%.32g\n\",0.99999999976716936);"
0.99999999976716925

C:\_32\pscrpt>perl -e "printf(\"%.32g\n\",9.9999999976716936e-1);"
0.99999999976716936

Since 0.99999999976716936 == 9.9999999976716936e-1, I can think of no
good reason that that those 2 one-liners should produce different
output - and I believe the first one liner produces an incorrect
result.

I'll submit a bug report about this - unless someone can convince me
that it's *not* a bug (or unless someone else wants to submit the
report).

Cheers,
Rob

Mirco Wahab

unread,
Apr 2, 2008, 10:25:57 AM4/2/08
to
sisyphus wrote:
> On Apr 2, 9:21 pm, vivekanand.n...@gmail.com wrote:
>> printf("%.32g\n",0.99999999976716936);
>> Perl 5.6.1 output:
>> 0.99999999976716936 --> GOOD
>> Perl 5.8.6 output:
>> 0.99999999976716925 --> ERROR
> I believe it's a bug in perl 5.8 (which has been carried through to
> perl 5.10):
> C:\_32\pscrpt>perl -e "printf(\"%.32g\n\",0.99999999976716936);"
> 0.99999999976716925
> C:\_32\pscrpt>perl -e "printf(\"%.32g\n\",9.9999999976716936e-1);"
> 0.99999999976716936
>
> Since 0.99999999976716936 == 9.9999999976716936e-1, I can think of no
> good reason that that those 2 one-liners should produce different
> output - and I believe the first one liner produces an incorrect
> result.
>
> I'll submit a bug report about this - unless someone can convince me
> that it's *not* a bug (or unless someone else wants to submit the
> report).

Seems to be dependend on the underlying C library
implementation. Consider the following program round.c:
----- [round.c] -----
#include "stdio.h"
int main() {
printf("0.99999999976716936\n");
printf("%.32g | %.36f\n", 0.99999999976716936, 0.99999999976716936);
printf("%.32g | %.36f (%s)\n",9.9999999976716936e-1,9.9999999976716936e-1,"sisyphus");
return 0;
}
--------------------

Results:
=========
Linux/gcc: gcc-4.3 -o round round.c ; ./round

0.99999999976716936
0.99999999976716935634613037109375 | 0.999999999767169356346130371093750000
0.99999999976716935634613037109375 | 0.999999999767169356346130371093750000 (sisyphus)

WinXP/Visual-C++ 2005 & Visual C++6.0 (same results):

0.99999999976716936
0.99999999976716936 | 0.999999999767169360000000000000000000
0.99999999976716936 | 0.999999999767169360000000000000000000 (sisyphus)


WinXP/MinGW 3.4.2

0.99999999976716936
0.99999999976716936 | 0.999999999767169360000000000000000000
0.99999999976716936 | 0.999999999767169360000000000000000000 (sisyphus)


Regards

M.

szr

unread,
Apr 2, 2008, 11:41:53 AM4/2/08
to
vivekan...@gmail.com wrote:
> printf("%.32g\n",0.99999999976716936);
>
> Perl 5.6.1 output:
> 0.99999999976716936 --> GOOD
>
> Perl 5.8.6 output:
> 0.99999999976716925 --> ERROR

I get:

$ perlall -e 'printf("%.32g\n",0.99999999976716936);'
<perl5.10.0> 0.99999999976716935997820764892019
<perl5.8.8 > 0.99999999976716935997820764892019
<perl5.8.2 > 0.9999999997671692453238279085781
<perl5.8.0 > 0.9999999997671692453238279085781
<perl5.6.1 > 0.99999999976716935634613037109375

--
szr


szr

unread,
Apr 2, 2008, 11:53:25 AM4/2/08
to


The version of Math::BigFloat that shipped with 5.6.1, which the op
seems to need, doesn't seem to support ->bstr()

$ perlall -MMath::BigFloat -e 'print
Math::BigFloat->new("0.99999999976716936")->bstr(), "\n";'
<perl5.10.0> 0.99999999976716936
<perl5.8.8 > 0.99999999976716936
<perl5.8.2 > 0.99999999976716936
<perl5.8.0 > 0.99999999976716936
Can't locate object method "bstr" via package "Math::BigFloat" (perhaps
you forgot to load "Math::BigFloat"?) at -e line 1.
<perl5.6.1 >


Perhaps ->ffround(17) could be used instead?

$ perl5.6.1 -MMath::BigFloat -e 'print
Math::BigFloat->new("0.99999999976716936")->ffround(-17), "\n";'
+99999999976716936E-17

You could always update your Math::* modules if you must use 5.6.1,
else, it would better to just install a newer Perl :-)

--
szr


szr

unread,
Apr 2, 2008, 12:02:34 PM4/2/08
to

Interesting, I get these values:

$ perlall -e 'printf("%.32g\n",99999999976716936e-1);'
<perl5.10.0> 9999999997671693.599609375
<perl5.8.8 > 9999999997671693.599609375
<perl5.8.2 > 9999999997671692
<perl5.8.0 > 9999999997671692
<perl5.6.1 > 9999999997671694

--
szr


szr

unread,
Apr 2, 2008, 12:05:59 PM4/2/08
to

Please disregard my previous reply, I made a dump typo.

This is what I get:

$ perlall -e 'printf("%.32g\n",9.9999999976716936e-1);'
<perl5.10.0> 0.99999999976716935997820764892019
<perl5.8.8 > 0.99999999976716935997820764892019
<perl5.8.2 > 0.99999999976716935634613037109375
<perl5.8.0 > 0.99999999976716935634613037109375
<perl5.6.1 > 0.99999999976716935634613037109375

--
szr


Ilya Zakharevich

unread,
Apr 2, 2008, 3:58:34 PM4/2/08
to
[A complimentary Cc of this posting was sent to
sisyphus
<sisyp...@gmail.com>], who wrote in article <28eff3d6-c1b4-4679...@i7g2000prf.googlegroups.com>:
> Since 0.99999999976716936 =3D=3D 9.9999999976716936e-1

Why this would be so? At best, one is 0.99999999976716936, another is
9.9999999976716936/10. I know no axiom of FP arithmetic which would
make them equal...

(In principle, one could impose a condition on atof() that all strings
are first normalized IN DECIMAL to the e00 exponent, THEN translated
to binary. But given that, AFAIK, atof() is not documented to satisfy
ANY requirement, however reasonable, this is a pipe dream.)

[I have, on a backburner, some plans to make Perl use "the best"
string-to-FP-to-string conversions (so that a lot of verbiage can be
removed from perlnumber.pod). But my improve-perl plans do not get a
lot of timeslices recently.]

Yours,
Ilya

sisyphus

unread,
Apr 2, 2008, 7:41:56 PM4/2/08
to
On Apr 3, 6:58 am, Ilya Zakharevich <nospam-ab...@ilyaz.org> wrote:
> [A complimentary Cc of this posting was sent to
> sisyphus
> <sisyphus...@gmail.com>], who wrote in article <28eff3d6-c1b4-4679-9838-38c295b4d...@i7g2000prf.googlegroups.com>:
>
> > Since 0.99999999976716936 =3D=3D 9.9999999976716936e-1
>
> Why this would be so?  At best, one is 0.99999999976716936, another is
> 9.9999999976716936/10.  I know no axiom of FP arithmetic which would
> make them equal...

Oh! ... ok. (I was thinking that perl should see the same mantissa in
both instances, and therefore store the same value.)

The other thing I note is that (with 52 bits of precision, plus the
implicit leading "1.") 0.99999999976716936 is represented in base 2
as:
1.1111111111111111111111111111111000000000000000000000e-1
And that converts back to 0.99999999976716936 (in base 10).

OTOH, 0.99999999976716925 is represented as:
1.1111111111111111111111111111110111111111111111111111e-1
And that converts back to 0.99999999976716925 (in base 10).

For my conversions, I'm using "round to nearest" mode - and I'm using
the mpfr C library (version 2.3.1) - which, according to its homepage
at http://www.mpfr.org/ provides "correct rounding" and "copies the
good ideas from the ANSI/IEEE-754 standard for double-precision
floating-point arithmetic (53-bit mantissa)". I've not yet had any
cause to take issue with those claims.

For me, (the recent versions of)perl are at odds with everything else
on my box in (apparently) insisting that 0.99999999976716936 has the
internal base 2 representation of:
1.1111111111111111111111111111110111111111111111111111e-1

Everything else uses an internal representation of
1.1111111111111111111111111111111000000000000000000000e-1.

Is that still not a perl bug ? (This FP stuff is just so damned
tricky, I never know what to think for sure :-)

Cheers,
Rob

Ben Morrow

unread,
Apr 2, 2008, 8:08:59 PM4/2/08
to

Quoth sisyphus <sisyp...@gmail.com>:

>
> For me, (the recent versions of)perl are at odds with everything else
> on my box in (apparently) insisting that 0.99999999976716936 has the
> internal base 2 representation of:
> 1.1111111111111111111111111111110111111111111111111111e-1

Do you know how it gets to that? Is it not simply calling your atof?

> Everything else uses an internal representation of
> 1.1111111111111111111111111111111000000000000000000000e-1.
>
> Is that still not a perl bug ? (This FP stuff is just so damned
> tricky, I never know what to think for sure :-)

I think the stated position is 'perl provides no guarantees about
anything to do with FP'. If you wish to implement, test, and document
something more consistent, please feel free.... :)

Ben

Ilya Zakharevich

unread,
Apr 2, 2008, 9:30:28 PM4/2/08
to
[A complimentary Cc of this posting was sent to
sisyphus
<sisyp...@gmail.com>], who wrote in article <9223ba3f-712a-42f6...@b5g2000pri.googlegroups.com>:
> For me, (the recent versions of)perl are at odds with everything else
> on my box in (apparently) insisting that 0.99999999976716936 has the
> internal base 2 representation of:
> 1.1111111111111111111111111111110111111111111111111111e-1
>
> Everything else uses an internal representation of
> 1.1111111111111111111111111111111000000000000000000000e-1.
>
> Is that still not a perl bug ? (This FP stuff is just so damned
> tricky, I never know what to think for sure :-)

You may want to consult

perl -V:d_Gconvert

It might help you understand what happens...

Yours,
Ilya

Ilya Zakharevich

unread,
Apr 2, 2008, 10:09:19 PM4/2/08
to
[A complimentary Cc of this posting was NOT [per weedlist] sent to
Ilya Zakharevich
<nospam...@ilyaz.org>], who wrote in article <ft1bvk$12uu$1...@agate.berkeley.edu>:

> > For me, (the recent versions of)perl are at odds with everything else
> > on my box in (apparently) insisting that 0.99999999976716936 has the
> > internal base 2 representation of:
> > 1.1111111111111111111111111111110111111111111111111111e-1
> >
> > Everything else uses an internal representation of
> > 1.1111111111111111111111111111111000000000000000000000e-1.
> >
> > Is that still not a perl bug ? (This FP stuff is just so damned
> > tricky, I never know what to think for sure :-)
>
> You may want to consult
>
> perl -V:d_Gconvert
>
> It might help you understand what happens...

Oups, it is THE OTHER direction! In fact, I do not know what Perl
uses to parse FP numbers. Let me check.... In 5.8.8:

#define Atof my_atof

which, essentially, calls Perl_my_atof2(), which OMG! calls a
home-brewed implementation! Shame on us! No wonder it behaves
fishy; coding string-to-num conversion is not for weaklings...

But before ringing the bell, please consider what is the *right*
answer. E.g.,

0.99999999976716936 * 2**75
= 37778931854161068825399.29174657778843648

The integer part is essentially

0b111111111111111111111111111111110000000000000000000000000100000001010111001

Perl behaves as if it were

0b11111111111111111111111111111110111111111111111111111...

The rest as if it were

0b11111111111111111111111111111111000000000000000000000...

So indeed, Perl's implemenation is extremely buggy (as anything
written by people who do not LIVE WITH FP would be)...

Hope this helps,
Ilya

Ilya Zakharevich

unread,
Apr 3, 2008, 12:33:21 AM4/3/08
to
[A complimentary Cc of this posting was sent to
sisyphus
<sisyp...@gmail.com>], who wrote in article <9223ba3f-712a-42f6...@b5g2000pri.googlegroups.com>:
> For me, (the recent versions of)perl are at odds with everything else
> on my box in (apparently) insisting that 0.99999999976716936 has the
> internal base 2 representation of:
> 1.1111111111111111111111111111110111111111111111111111e-1
>
> Everything else uses an internal representation of
> 1.1111111111111111111111111111111000000000000000000000e-1.

Yet another thought (that's just alias for Perl's printf):

pprintff .31g 0.99999999976716936
0.999999999767169245324

pprintff .31g 99999999976716936/100000000000000000
0.999999999767169245324

pprintff .31g 99999999976716936
99999999976716928

So it looks like whoever wrote Perl's Atof() thought (in their greate
wiseness) that one is allowed to translate the mantissa in 3
operations: convert the "integer mantissa" to an FP value, then
convert the corresponding 1000...000 to an FP value, then divide.

(The numerics people would immediately note that doing 3 operations
increases the maximal possible error 3 times, which is not allowed.
The trickyness of string-to-FP conversion is that it cannot be done
using just the precision of the FP primitives; one needs to get a
higher precision that this...)

Hope this helps,
Ilya

Ted Zlatanov

unread,
Apr 3, 2008, 10:54:50 AM4/3/08
to
On Thu, 3 Apr 2008 01:08:59 +0100 Ben Morrow <b...@morrow.me.uk> wrote:

BM> I think the stated position is 'perl provides no guarantees about
BM> anything to do with FP'.

Position of who?

There's Math::BigFloat and Math::BigRat which are at least moderately
useful.

Ted

Ben Morrow

unread,
Apr 3, 2008, 5:54:51 PM4/3/08
to

Quoth Ted Zlatanov <t...@lifelogs.com>:

> On Thu, 3 Apr 2008 01:08:59 +0100 Ben Morrow <b...@morrow.me.uk> wrote:
>
> BM> I think the stated position is 'perl provides no guarantees about
> BM> anything to do with FP'.
>
> Position of who?

Whom. :-)

Of p5p, but note that I don't speak for 'them' in any way, so I may be
mis-stating the case.

> There's Math::BigFloat and Math::BigRat which are at least moderately
> useful.

There are; there are also the bigint and bignum pragmata which make them
more useful still. I was talking about perl's handling of real platform
floats (NVs).

Ben

Ilya Zakharevich

unread,
Apr 3, 2008, 6:23:45 PM4/3/08
to
[A complimentary Cc of this posting was sent to
sisyphus
<sisyp...@gmail.com>], who wrote in article <9223ba3f-712a-42f6...@b5g2000pri.googlegroups.com>:
> > > Since 0.99999999976716936 == 9.9999999976716936e-1

> >
> > Why this would be so? At best, one is 0.99999999976716936, another is
> > 9.9999999976716936/10. I know no axiom of FP arithmetic which would
> > make them equal...
>
> Oh! ... ok. (I was thinking that perl should see the same mantissa in
> both instances, and therefore store the same value.)

Note that in other posts I flipped my position in this question.
According to the semantic in perlnumber.pod, a decimal string should
be considered as the REAL (as opposite to FP!) number exactly
representable by this decimal. When needed for its operation, Perl
has the right to convert it to the closest exactly representable FP
number.

In particular, in Perl one must have

0.99999999976716936 == 9.9999999976716936e-1

[As far as Perl was using CRT library routines for string-to-FP
conversion, there were an excuse for some deviations from this
semantic. However, since nowadays uses its own routine, no such
deviation may be allowed.]

Yours,
Ilya

Ted Zlatanov

unread,
Apr 4, 2008, 11:45:41 AM4/4/08
to
On Thu, 3 Apr 2008 22:54:51 +0100 Ben Morrow <b...@morrow.me.uk> wrote:

BM> Quoth Ted Zlatanov <t...@lifelogs.com>:


>> On Thu, 3 Apr 2008 01:08:59 +0100 Ben Morrow <b...@morrow.me.uk> wrote:
>>
BM> I think the stated position is 'perl provides no guarantees about
BM> anything to do with FP'.
>>
>> Position of who?

BM> Whom. :-)

Eh, if I remembered those grammar rules I'd have no room in my brain for
what $| does :)

BM> Of p5p, but note that I don't speak for 'them' in any way, so I may be
BM> mis-stating the case.

I'm curious if there are, in fact, some guarantees. For example, "on a
full moon, under the willow tree, while softly singing the songs of
distant Earth, adding two floats will, sometimes, give you a float that
is roughly equal to their sum." You know, spice up the docs a bit.

>> There's Math::BigFloat and Math::BigRat which are at least moderately
>> useful.

BM> There are; there are also the bigint and bignum pragmata which make them
BM> more useful still. I was talking about perl's handling of real platform
BM> floats (NVs).

Right, but big* is a FP interface that's quite useful, and should at
least be mentioned when people complain about platform floats. Then
those same people can complain about big* performance and Intel/AMD can
sell them faster processors. Everybody wins.

Ted

sisyphus

unread,
Apr 7, 2008, 9:12:15 AM4/7/08
to
On Apr 3, 10:08 am, Ben Morrow <b...@morrow.me.uk> wrote:
.
.

> Is it not simply calling your atof?

I don't think so - and I see, further down, that Ilya has reported it
calls a "home-brewed" implementation.

I tried out ActiveState's builds of perl 5.6.1, 5.8.8 and 5.10.0 - all
three of which use the same underlying C library (Visual Studio 6.0).

Again, with their 5.6 build I get:

C:\_32\pscrpt>perl -e "printf(\"%.32g\n\",9.9999999976716936e-1);"
0.99999999976716936

Yet, with their builds of 5.8 and 5.10 I get:

C:\_32\pscrpt>perl -e "printf(\"%.32g\n\",9.9999999976716936e-1);"

0.99999999976716925

I think that rules out differences in the C library as the cause of
the discrepancy.

As regards atof() itself, the following C program outputs
0.99999999976716936:

int main( void )
{
double x;

x = atof("0.99999999976716936");
printf( "%.17f\n", x );

}

Cheers,
Rob

0 new messages