# Generating equally-spaced floats with least rounding error

Steven D'Aprano steve+comp.lang.python at pearwood.info
Sun Sep 25 07:31:14 CEST 2011

```Chris Angelico wrote:

> On Sun, Sep 25, 2011 at 3:01 AM, 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?
>>>
>> Ah, I knew it was too easy!
>
> Try using Fraction for the start and stop too:

If you look again at the code I used, I did. I just did it inside the list
comp.

>>>> from fractions import Fraction as F
>>>> start,stop,n = F(0),F(21,10),7
>>>> [float(start+i*(stop-start)/n) for i in range(n+1)]
> [0.0, 0.3, 0.6, 0.9, 1.2, 1.5, 1.8, 2.1]
>>>> [float(start+i*(stop-start)/n) for i in range(n+1)]
> [-1.0, -0.7, -0.4, -0.1, 0.2, 0.5, 0.8, 1.1]

Something looks a tad suspicious here... the two list comps are identical,
but give completely different results, even though you don't re-assign
start and stop between calls. You're not editing your results are you?
<wink>

But seriously, you were freaking me out there for a bit. I couldn't see why
pulling the conversion to fraction outside of the list comp was giving
different results. And then it hit me...

>>> 2.1 == F(21, 10)
False

You're testing different numbers from me. Try again with F(2.1) as the stop
value.

--
Steven

```