Generating equally-spaced floats with least rounding error

Arnaud Delobelle arnodel at gmail.com
Sat Sep 24 21:55:34 CEST 2011


On 24 September 2011 18:01, Steven D'Aprano
<steve+comp.lang.python at pearwood.info> wrote:
> Mark Dickinson wrote:
>
>> Using Fraction for intermediate calculations actually works perfectly
>> for this, since conversions from float to Fraction are exact, while
>> conversions from Fraction to float are correctly rounded.  So if
>> you're using Python, you're not too bothered about efficiency, and you
>> want provably correctly-rounded results, why not use Fraction?
>>
>>>>> from fractions import Fraction
>>>>> start, stop, n = 0.0, 2.1, 7
>>>>> [float(Fraction(start) + i * (Fraction(stop) - Fraction(start)) / n)
>>>>> [for i in range(n+1)]
>> [0.0, 0.3, 0.6, 0.9, 1.2, 1.5, 1.8, 2.1]
>
>
> Ah, I knew it was too easy!
>
>>>> from fractions import Fraction as F
>>>> start, stop, n = 1, 3.1, 7
>>>> [float(F(start) + i*(F(stop)-F(start))/n) for i in range(n+1)]
> [1.0, 1.3, 1.6, 1.9000000000000001, 2.2, 2.5, 2.8000000000000003, 3.1]

>>> start, stop, n = 1, 3.1, 7
>>> [((n-i)*start + i*stop)/n for i in range(n+1)]
[1.0, 1.3, 1.5999999999999999, 1.9000000000000001, 2.2, 2.5,
2.8000000000000003, 3.1]

>>>> start, stop, n = -1, 1.1, 7
>>>> [float(F(start) + i*(F(stop)-F(start))/n) for i in range(n+1)]
> [-1.0, -0.7, -0.39999999999999997, -0.09999999999999996,
> 0.20000000000000004, 0.5000000000000001, 0.8, 1.1]

>>> start, stop, n = -1, 1.1, 7
>>> [((n-i)*start + i*stop)/n for i in range(n+1)]
[-1.0, -0.7000000000000001, -0.39999999999999997,
-0.09999999999999996, 0.20000000000000004, 0.5, 0.8, 1.1]

On these examples, using fractions is no better than what I suggested
in my previous post.

-- 
Arnaud



More information about the Python-list mailing list