Generating equally-spaced floats with least rounding error
Steven D'Aprano
steve+comp.lang.python at pearwood.info
Sat Sep 24 15:53:26 CEST 2011
I'm trying to generate a sequence of equally-spaced numbers between a lower
and upper limit. Given arbitrary limits, what is the best way to generate a
list of equally spaced floats with the least rounding error for each point?
For example, suppose I want to divide the range 0 to 2.1 into 7 equal
intervals, then the end-points of each interval are:
(0.0)---(0.3)---(0.6)---(0.9)---(1.2)---(1.5)---(1.8)---(2.1)
and I'd like to return the values in the brackets. Using Decimal or Fraction
is not an option, I must use floats. If the exact value isn't representable
as a float, I'm okay with returning the nearest possible float.
The width of each interval is:
width = (2.1 - 0.0)/7
The relevant points can be calculated in either of two methods:
#1 add multiples of the width to the starting value, 0.
#2 subtract multiples of width from the ending value, 2.1.
(Repeated addition or subtraction should be avoided, as it increases the
amount of rounding error.)
Mathematically the two are equivalent, but due to rounding, they may not be.
Here's a run using Python 3.2:
>>> [0.0 + i*width for i in range(8)]
[0.0, 0.3, 0.6, 0.8999999999999999, 1.2, 1.5, 1.7999999999999998, 2.1]
The 4th and 7th values have rounding errors, the rest are exact.
>>> [2.1 - (7-i)*width for i in range(8)]
[0.0, 0.30000000000000027, 0.6000000000000001, 0.9000000000000001,
1.2000000000000002, 1.5, 1.8, 2.1]
The 2nd, 3rd, 4th and 5th values have rounding errors. Note that the 7th
value is exact here, but not above.
Is there a way to pick between methods #1 and #2 (or some combination of the
two) without human intervention so as to minimise the rounding error? Or is
there some other way to generate equally-spaced floats? My efforts at
googling have not been helpful.
--
Steven
More information about the Python-list
mailing list