Boost logo

Boost :

Subject: Re: [boost] MS VC10 std::numeric_limits<float>::max_digits10 iswrong for float
From: Paul A. Bristow (pbristow_at_[hidden])
Date: 2011-06-09 05:33:08


> -----Original Message-----
> From: boost-bounces_at_[hidden] [mailto:boost-bounces_at_[hidden]] On Behalf Of Fernando
> Cacciola
> Sent: Thursday, June 09, 2011 4:35 AM
> To: boost_at_[hidden]
> Subject: Re: [boost] MS VC10 std::numeric_limits<float>::max_digits10 iswrong for float
>
> On 08-Jun-11 9:32 PM, Stephan T. Lavavej wrote:
> > Separately, Dinkumware has told me that 8 really is the right answer here, not 9.
>
> Hmmm... then if they are right, we're all wrong, because 9 is the number I've always seen as
correct.
>
> OTOH, we *could* have been all wrong, all alone, since this is the sort of thing that just gets
perpetuated
> from publication to publication and mouth to mouth.
>
> Do they explained why? [Are P.J. and Pete still the ones behind these things?]

Well I was surprised to notice the value 8 and so I re-ran my existing loopback test (that had
previously worked OK for float, but not for double). (This test was purely for convenience - takes
all night to run, brute force is possible for float whereas for double test all possible values
would take 35 years at current processor speeds! (though a random test did reveal loopback fails
with doubles with the Dinkumware library, allegedly a feature, not a bug). It was devised to check
if loopback (output to a string and reading back in) works OK (a separate issue, but if
max_digits10 is wrong, loopback will fail).

This issue is NOT about loopback (which is NOT guaranteed by the C++ Standard) but about
max_digits10.

So I ran a much simple test and found quite a few values of float that give the same decimal digit
string for 1-bit different binary patterns.

But it only takes one value that 'fails' for 8 to be wrong, and a simple example is below:

 union ful
{ // Used to enable output of float in hex.
   float f;
  unsigned long u;
};

int main()
{
  ful f1;
  f1.f= 1.10000006e-032f;
  ful f2;
  f2.f = 1.10000014e-032f; // 1 bit greater in FP binary pattern, see hex display below

  cout << "f1 " << setprecision(8) << "precision 8 " << f1.f << endl;
  cout << "f1 "<< setprecision(9) << "precision 9 " << f1.f << endl;
  cout << "f1 " << hex << f1.u << endl;

  cout << "f2 " << setprecision(8) << "precision 8 " << f2.f << endl;
  cout << "f2 " << setprecision(9) << "precision 9 " << f2.f << endl;
  cout << "f2 " << hex << f2.u << endl;
  return 0;
}

 f1 precision 8 1.1000001e-032
 f1 precision 9 1.10000006e-032
  f1 a647609

  f2 precision 8 1.1000001e-032 <<<<<<<<<< note this is the same as f1 above using 8.
  f2 precision 9 1.10000014e-032 <<<< but f1 and f2 are different using 9.
  f2 a64760a <<<<<<<<<< note f2 really is one bit greater and so should have a different decimal
digits string representation.

I hope this is convincing - I conclude that Kahan was right, and is still is ;-)

Paul

---
Paul A. Bristow,
Prizet Farmhouse, Kendal LA8 8AB  UK
+44 1539 561830  07714330204
pbristow_at_[hidden]

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk