Floating point issues
Ross Paterson
ross at soi.city.ac.uk
Thu Jun 8 12:06:37 EDT 2006
On Thu, Jun 08, 2006 at 10:26:49AM +0100, Neil Mitchell wrote:
> Consider the following examples:
>
> Hugs> 3 ** 2
> 9.0
> Hugs> 3 ** 2 :: Float
> 9.0
> Hugs> 3 ** 2 :: Double
> 9.0
> Hugs> 3 ** 2 == 9
> False
> Hugs> 3 ** 2 == (9::Double)
> False
> Hugs> 3 ** 2 == (9::Float)
> True
>
> Note that GHC gets the sensible answer of True for all these cases. I
> also tested this on Linux Hugs with the same results as WinHugs.
>
> This doesn't seem that logical - I know floating point == is just
> asking for trouble, but why is the less precise one keeping the
> correct answer? Also it seems weird not to have the property that read
> . show = id and that show a == show b => a == b
Hugs uses the Haskell 98 default definition of (**):
x ** y = exp (log x * y)
GHC uses a specialized definition of (**) that happens to give 9.0,
but the default definition gives this answer (in ghci):
Prelude> exp (log 3 * 2) :: Double
9.000000000000002
Hugs gets the same answer, but shows it incorrectly. This is a
documented bug (section 5.1.5 of the User's Guide): Haskell 98 has a
precise definition of show on these types that does indeed satisfy those
equations, but Hugs uses printf instead, to avoid a lot of extra code
in the Prelude. So
Hugs> 3 ** 2 :: Double
9.0
Hugs> 3 ** 2 - 9 :: Double
1.77635683940025e-15
As for Float, Hugs does all operations in double and then truncates to
float, and in this case truncation wipes out the small error.
As you say, floating point is notorious for this sort of thing.
The only real bug here is in Hugs's show.
More information about the Hugs-Bugs
mailing list