[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
> 
> 
> ------------------------------------------------------------------------
> 
> _______________________________________________
> Haskell-Cafe mailing list
> Haskell-Cafe at haskell.org
> http://www.haskell.org/mailman/listinfo/haskell-cafe



More information about the Haskell-Cafe mailing list