5

Simple question: what is the correct bit-representation of the number 1.15507e-173, in double precision? Full question: how does one determine the correct parsing of this number?

Background: my question follows from this answer which shows two different bit-representations from three different parsers, namely

0x1c06dace8bda0ee0

and

0x1c06dace8bda0edf

and I'm wondering which parser has got it right.

Update Section 6.4.4.2 of the C99 specification says that for the C parser,

"...the result is either the nearest representable value, or the larger
or smaller representable value immediately adjacent to the nearest
representable value, chosen in an implementation-defined manner."

This implies that the parsed number need not be the nearest, nor even one of the two adjacent representable numbers. The same spec in 7.20.1.3 says that strtod() behaves essentially the same way as the built-in parser. Thanks to the answerers who pointed this out.

Also see this answer to a similar question, and this blog.

Community
  • 1
  • 1
Gavin Band
  • 71
  • 4
  • What does the C parser say? GCC 4.6 uses MPFR internally I believe, so I'd expect the result to be as accurate as possible. – Kerrek SB Aug 03 '11 at 10:17
  • 1
    There is no "correct" - I assume without checking that both of those answers are within one ULP of the mathematically exact value of `1.15507e-173`, since they're only 1 ULP apart. The C standard doesn't say which one the implementation must produce. IEEE 754 defines rounding modes, but I don't know whether it says anything about how they affect `strtod`. – Steve Jessop Aug 03 '11 at 10:17
  • Why this particular number anyway? Is that the one related to some recent bug? – Kerrek SB Aug 03 '11 at 10:27
  • @Steve, note 305 seems to imply that pragma STDC FENC_ACCESS influences strtod. – AProgrammer Aug 03 '11 at 12:46
  • @Kerrek, the number has no particular significance; it's just one that I found that shows a discrepancy. The C parser gives the first value, as does my system's strtod(). – Gavin Band Aug 03 '11 at 15:07
  • @Steve, thanks for the comment. Is it that my number is equidistant between two representable ones, and the two implementations are rounding in different ways? – Gavin Band Aug 03 '11 at 15:12
  • @Gavin: It's not exactly equidistant, because its binary decimal representation doesn't terminate. `strtod` says that the value is interpreted as a floating-point constant would be. 6.4.4.2/3 of C99 says "either the nearest representable value, or the larger or smaller representable value immediately adjacent to the nearest representable value, chosen in an implementation-defined manner". So that's how much inaccuracy is tolerated, it's possible they're both correct even if (as Artefacto says), they're both the same side of the true value. – Steve Jessop Aug 03 '11 at 15:30
  • I see two 32 bit representations. Are you sure they are doubles? – Rudy Velthuis Aug 03 '11 at 20:01

1 Answers1

1
:= num1 = ImportString["\.1c\.06\.da\.ce\.8b\.da\.0e\.e0", "Real64", ByteOrdering->1] // First;
:= num2 = ImportString["\.1c\.06\.da\.ce\.8b\.da\.0e\.df", "Real64", ByteOrdering->1] // First;
:= SetPrecision[num1, Infinity]-numOr //N
:= numOr =  SetPrecision[1.15507, Infinity] * 10^-173;
             -190
= -6.65645 10
:= SetPrecision[num2, Infinity]-numOr //N
             -189
= -2.46118 10

Given that both deviate for the same side, it follows that the correct representation is the first one.

Artefacto
  • 96,375
  • 17
  • 202
  • 225
  • @Gavin There's no much to it, it reads the ieee 754 representation of the doubles, [converts them to infinite precision](http://reference.wolfram.com/mathematica/ref/SetPrecision.html) numbers and then checks how far they are from your target. – Artefacto Aug 03 '11 at 18:44