[Tutor] range function and floats?
Wayne Werner
waynejwerner at gmail.com
Wed Jan 5 16:02:00 CET 2011
On Wed, Jan 5, 2011 at 5:14 AM, Steven D'Aprano <steve at pearwood.info> wrote:
> Alan Gauld wrote:
>
> ...this is more about learning how the range function and floats work than
>>> about writing a super-efficient program.
>>>
>>
>> Unfortunately they don't work together.
>>
>> range(0.1,0.5,0.1) -> [0.1,0.2,0.3,0.4] doesn't work
>> you need to do:
>>
>> for n in range(1,5): use( n/10 )
>>
>
>
> There are pitfalls in writing a range() equivalent for floats. Here's one
> way that doesn't work:
>
>
> def new_range(start, end, step):
> # DON'T USE THIS!!!
> x = start
> while x < end:
> yield x
> x += step
>
> Here it seems to work:
>
> >>> list(new_range(5, 10, 0.25))
> [5, 5.25, 5.5, 5.75, 6.0, 6.25, 6.5, 6.75, 7.0, 7.25, 7.5,
> 7.75, 8.0, 8.25, 8.5, 8.75, 9.0, 9.25, 9.5, 9.75]
>
> (Remember that the end argument is excluded!)
>
> But here it fails:
>
>
> >>> L = list(new_range(5, 10, 0.1))
> >>> L[-1] == 9.9 # expect the last value to be 9.9
> False
> >>> L[-1] == 10.0 # maybe it's 10 then
> False
>
> In fact, the last value is a totally unexpected 9.9999999999999822. Such is
> the perils of floating point rounding errors.
>
> I've written a recipe for a float range which I hope avoids as many of
> these problems as possible. It isn't possible to avoid *all* rounding error
> when doing floating point calculation, but this should minimize them:
>
> http://code.activestate.com/recipes/577068-floating-point-range/
>
> As a bonus, it allows you to choose whether the start and end points are
> included or excluded.
As an alternative to floating point, you can use the Decimal module:
import decimal
def new_range(start, stop, step):
x = decimal.Decimal(str(start))
step = decimal.Decimal(str(step))
while x < stop:
yield x
x += step
x = list(new_range(5, 10, 0.1))
x[-1] == decimal.Decimal(str(9.9))
#True
float(x[-1]) == 9.9
#True
The decimal module allows you to get rid of those pesky floating point
errors. See http://docs.python.org/library/decimal.html for more info. On a
related note, if you're interested in working with rational numbers (1/23,
3/4, etc.) there is also a fraction module
http://docs.python.org/library/fractions.html.
HTH,
Wayne
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/tutor/attachments/20110105/ea0d7bb5/attachment-0001.html>
More information about the Tutor
mailing list