Gal A. February 2016

range-like function for floats

I wanted to use the built-in range function for floats, but apparently it doesn't work and from a quick research, i understood that there isn't a built in option for that and that I'll need to code my own function for this. So I did:

def fltrange(mini, maxi, step):
lst = []
while mini < maxi:
    lst.append(mini)
    mini += step
return lst
 rang = fltrange(-20.0, 20.1, 0.1)
 print(rang)
 input()

but this is what I get: result

the step should be just 0.1000000..., but instead it's about (sometimes it changes) 0.100000000000001.

Thanks in advance.

Answers


Kevin February 2016

Fun fact: 1/10 can't be exactly represented by floating point numbers. The closest you can get is 0.1000000000000000055511151231257827021181583404541015625. The rightmost digits usually get left out when you print them, but they're still there. This explains the accumulation of errors as you continually add more 0.1s to the sum.

You can eliminate some inaccuracy (but not all of it) by using a multiplication approach instead of a cumulative sum:

def fltrange(mini, maxi, step):
    lst = []
    width = maxi - mini
    num_steps = int(width/step)
    for i in range(num_steps):
        lst.append(mini + i*step)
    return lst
rang = fltrange(-20.0, 20.1, 0.1)
print(rang)

Result (newlines added by me for clarity):

[-20.0, -19.9, -19.8, -19.7, -19.6, -19.5, -19.4, -19.3, -19.2, -19.1, 
-19.0, -18.9, -18.8, -18.7, -18.6, -18.5, -18.4, -18.3, -18.2, -18.1, 
-18.0, -17.9, -17.8, -17.7, -17.6, -17.5, -17.4, -17.3, -17.2, -17.1, 
-17.0, -16.9, -16.8, -16.7, -16.6, -16.5, -16.4, -16.3, -16.2, -16.1, 
-16.0, -15.899999999999999, -15.8, -15.7, -15.6, -15.5, -15.399999999999999, -15.3, -15.2, -15.1, -15.0,
...
19.1, 19.200000000000003, 19.300000000000004, 19.400000000000006, 19.5, 19.6, 19.700000000000003, 19.800000000000004, 19.900000000000006, 20.0]


Alex Belyaev February 2016

You can use numpy for it. There are a few functions for your needs.

import numpy as np  # of course :)

linspace :

np.linspace(1, 10, num=200)
array([  1.        ,   1.04522613,   1.09045226,   1.13567839,
         1.18090452,   1.22613065,   1.27135678,   1.31658291,
         ...
         9.68341709,   9.72864322,   9.77386935,   9.81909548,
         9.86432161,   9.90954774,   9.95477387,  10.        ])

arange :

np.arange(1., 10., 0.1)
array([ 1. ,  1.1,  1.2,  1.3,  1.4,  1.5,  1.6,  1.7,  1.8,  1.9,  2. ,
        2.1,  2.2,  2.3,  2.4,  2.5,  2.6,  2.7,  2.8,  2.9,  3. ,  3.1,
        ...
        8.7,  8.8,  8.9,  9. ,  9.1,  9.2,  9.3,  9.4,  9.5,  9.6,  9.7,
        9.8,  9.9])

P.S. However, it's not technically a generator, which is a range in Python3 (xrange for Python2.x).

Post Status

Asked in February 2016
Viewed 3,723 times
Voted 8
Answered 2 times

Search




Leave an answer