# [Haskell-cafe] rounding errors with real numbers.

Lennart Augustsson lennart at augustsson.net
Sun Feb 26 10:28:02 EST 2006

```Well, if you are relying on exact results from floating point
arithmetic you're in trouble no matter what you do.
I would just ignore the slight error and when finally printing
the results do some rounding.  Trying to fudge things is just
going to bite you somewhere else.

(BTW, I much prefer the name "floating point" to "real".  I think
the latter should be reserved for when you actually have real numbers.)

-- Lennart

Matthias Fischmann wrote:
>
> hi,
>
> I think this is the well-known issue of using real numbers in decimal
> representation on a machine that thinks binary, but I don't know what
> to do with it, and some of you maybe do.
>
> I want to shift+stretch a list of doubles into a given interval.
> example:
>
> | x1 = [2, 3, 4, 5, 10]
> | y1 = normInterval x1 0 1
> | => y1 = [0.0,0.125,0.25,0.375,1.0]
>
> The function that does this looks something like this:
>
> | normInterval :: [Double] -> Double -> Double -> [Double]
> | normInterval ps lower upper = map (\ x -> (x - oldLower) * stretch + lower) ps
> |     where
> |     oldLower = head ps
> |     oldUpper = last ps
> |     stretch = (upper - lower) / (oldUpper - oldLower)
>
> However, with bigger numbers I get rounding errors:
>
> | x2 = [0.0,1.9569471624266144e-3,5.870841487279843e-3,1.5655577299412915e-2,3.913894324853229e-2,9.393346379647749e-2,0.2191780821917808,0.5009784735812133,1.1272015655577299,2.504892367906066]
> | y2 = normInterval x2 0 1
> | => y2 = [0.0,7.8125e-4,2.3437500000000003e-3,6.25e-3,1.5625000000000003e-2,3.7500000000000006e-2,8.750000000000001e-2,0.2,0.45000000000000007,0.9999999999999999]
>
> The solution that pops to my mind is very simple:
>
> | normInterval :: [Double] -> Double -> Double -> [Double]
> | normInterval ps lower upper = repair (map (\ x -> (x - oldLower) * stretch + lower) ps)
> |     where
> |     oldLower = head ps
> |     oldUpper = last ps
> |     stretch = (upper - lower) / (oldUpper - oldLower)
> |
> |     -- fix rounding error:
> |     repair [i] = [upper]
> |     repair (h:t) = h : repair t
>
> It works, but it's ugly.  Is there a better way to do this?
>
>
>
> Thanks,
> Matthias
>
>
> ------------------------------------------------------------------------
>
> _______________________________________________