
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