Opened 9 years ago

Closed 9 years ago

#4383 closed bug (fixed)

Uncanonical display of Double

Reported by: Owned by:
Priority: high Milestone: 7.0.2
Component: libraries/base Version: 6.12.3
Keywords: Double, show Cc: lennart@…
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: Incorrect result at runtime Test Case:
Blocked By: Blocking:
Related Tickets: Differential Rev(s):
Wiki Page:


Prelude> 0.5 ^ 1030

Should of course be 8.69...e-311, just to have it on record for now.

I'll take a look at the showing code one of the next days.

Attachments (5)

fix4383.dpatch (53.6 KB) - added by 9 years ago.
mDnTypo.dpatch (52.4 KB) - added by 9 years ago.
floatToDigitsPerformance.dpatch (53.0 KB) - added by 9 years ago.
cache.dpatch (52.6 KB) - added by 9 years ago.
fix4383-and-performance.dpatch (57.0 KB) - added by 9 years ago.

Download all attachments as: .zip

Change History (11)

comment:1 Changed 9 years ago by augustss

Cc: lennart@… added

That code is pretty impenetrable. :)

My guess is that the log estimator doesn't do the right thing for negative exponents. Try (fixup (k0-1)).

comment:2 Changed 9 years ago by

For starters, a better approximation to logBase 10 2 fixes this,

     if b == 2 && base == 10 then
        -- logBase 10 2 is slightly bigger than 3/10 so
        -- the following will err on the low side.  Ignoring
        -- the fraction will make it err even more.
        -- Haskell promises that p-1 <= logBase b f < p.
        -- (p - 1 + e0) * 3 `div` 10
        (p - 1 + e0) * 21306 `quot` 70777

*FloatShow> let x :: Double; x = 0.5 ^ 1030
*FloatShow> floatToDigits 10 x
*FloatShow> showFloat x ""

but I'd rather check the code carefully to see whether something else might need fixing (and maybe an earlier convergent of logBase 10 2 will suffice).

Changed 9 years ago by

Attachment: fix4383.dpatch added

Changed 9 years ago by

Attachment: mDnTypo.dpatch added

Changed 9 years ago by

Changed 9 years ago by

Attachment: cache.dpatch added

Changed 9 years ago by

comment:3 Changed 9 years ago by

Status: newpatch
  1. fix4383.dpatch fixes the issue, we no longer overestimate the base 10 logarithm
  2. There was a typo (b instead of be) in the distance to the next smaller FP number for powers of floatRadix. I thought it ought to be b^e and verified it in the paper. This makes numrun012 fail because now 2 ^ 31 :: Float shows as "2.1474836e9" instead of "2.1474837e9" (and some other show values change too, e.g. 2.0 ^ 852 was "3.0030067315218801e256" is now "3.00300673152188e256").
  3. Performance enhancement by using quot/quotRem instead of div/divMod and using the cache of powers of 2 instead of recomputing.
  4. Further performance enhancement by adding a cache for powers of 10.
  5. All of the above in one patch.
  1. and 2. should be applied since they correct errors.

The performance enhancement isn't too bad, I think a few more percent could be squeezed out, but it doesn't solve the fundamental problem of the slowness of show for RealFloat values (cf. I plan to look into it for 7.2, not now.

comment:4 Changed 9 years ago by simonmar

Milestone: 7.0.2
Priority: normalhigh

Thanks Daniel.

I presume we want the fixes in the 7.0 branch and the performance improvements in 7.2. Milestoning for 7.0.2 to get the fixes in initially.

comment:5 Changed 9 years ago by simonmar

Status: patchmerge

I pushed all these to HEAD. We want these two in 7.0.2:

Sun Oct 24 11:29:42 PDT 2010  Daniel Fischer <>
  * FIX #4383
  Use a better approximation to logBase 10 2 to prevent leading zeros in floatToDigits.

Sun Oct 24 19:50:41 BST 2010  Daniel Fischer <>
  * Fix typo in floatToDigits
  The mDn value for powers of 2 >= floatDigits x - 1 was typo'ed, leading to longer than necessary show results in a few cases (e.g. 2.0^852).
  Corrected in accordance with Burger and Dybvig's paper.

and these two should stay in HEAD only:

Sun Oct 24 20:07:07 BST 2010  Daniel Fischer <>
  * Cache for powers of 10
  Add a cache for commonly needed powers of 10 to speed up floatToDigits.

Sun Oct 24 19:59:14 BST 2010  Daniel Fischer <>
  * Performance enchancement for floatToDigits
  Use quot and quotRem instead of div and divMod for dividing positive Integers since that is a bit faster.

comment:6 Changed 9 years ago by igloo

Resolution: fixed
Status: mergeclosed

Both merged.

Note: See TracTickets for help on using tickets.