8

Possible Duplicate:
Python decimal range() step value

I would like generate list like this:

[0, 0.05, 0.1, 0.15 ... ]

range(0, 1, 0.05) would be great but it doesn't work beacuse:

range() integer step argument expected, got float.

Have you any elegant idea? ;)

Community
  • 1
  • 1
David Silva
  • 1,939
  • 7
  • 28
  • 60

5 Answers5

6

If you can use numpy, it's a good idea to use numpy.linspace. Functions that try to fit range logic on floating-point numbers, including numpy's own arange, usually get confusing regarding whether the end boundary ends up in the list or not. linspace elegantly resolves that by having you to explicitly specify the start point, the end point, and the desired number of elements:

>>> import numpy
>>> numpy.linspace(0.0, 1.0, 21)
array([ 0.  ,  0.05,  0.1 ,  0.15,  0.2 ,  0.25,  0.3 ,  0.35,  0.4 ,
        0.45,  0.5 ,  0.55,  0.6 ,  0.65,  0.7 ,  0.75,  0.8 ,  0.85,
        0.9 ,  0.95,  1.  ])
user4815162342
  • 141,790
  • 18
  • 296
  • 355
  • You can't win: `linspace` might get confusing about *how many items are there* ("why 21 and not 20?"). True that a comment would always be in order anyway. – LSerni Sep 13 '12 at 09:58
  • I was thinking the exact same thing while I was changing `20` to `21` after my initial example failed to work as expected. :) Still, this kind of confusion is much less subtle and prone to surprises than the confusion of whether the end point gets included in the range (and how to always make it there if it's not). It's always a tradeoff, but at least here it's obvious that you get what you asked for — `len` of the resulting array *is* 21. – user4815162342 Sep 13 '12 at 10:00
  • You *always* get what you ask for. That's the tragedy of programming :) – LSerni Sep 13 '12 at 10:03
  • You can specify if the last point should be included or not. Have a look at the `endpoint` argument. – Dr. Jan-Philip Gehrcke Sep 13 '12 at 10:59
6

In Python 3, range returns a generator (immutable sequence)... so I think we can define a very simple function like:

def frange(start,stop, step=1.0):
    while start < stop:
        yield start
        start +=step

So:

for x in frange(0, 1, 0.05):
   print(x)

Python doesn't need to be tricky.

If you want a list, just call:

list(frange(0,1,0.05))

Or change the function to return a list right away.

You can use one line solutions that multiply or do other stuff, but it can be tricky with different start and end values. If you use this kind of ranges frequently, just use the function and reuse it. Even a one-liner repeated many times on code is bad.

nmenezes
  • 910
  • 6
  • 12
  • This is kind of pedantic, but `range()` returns a list. `xrange()` returns a generator. – ATOMP Dec 14 '17 at 18:42
  • Not in Python 3. range returns a generator (immutable sequence) and xrange does not exist anymore. I will fix the print to make it clear it is python 3. – nmenezes Dec 15 '17 at 13:38
3

Or how about this:

[v*0.05 for v in range(0,int(1/0.05))]
Ivan Koblik
  • 4,285
  • 1
  • 30
  • 33
  • You risk to 'shave off' the last element, maybe. I think doing the division in the comprehension is clearer. On the other hand your method allows choosing whether to explicitly use rounding or truncating for range calculation, so it could be better in some cases. – LSerni Sep 13 '12 at 09:55
  • Alternatively you could always do the math yourself `[v*0.05 for v in range(0,20)]`, I just tried to show that one liner is possible :) – Ivan Koblik Sep 13 '12 at 09:59
  • 1
    Yes, that's why I +1'd your solution. But I'm more comfortable doing the math myself, and possibly explaining in the comment. – LSerni Sep 13 '12 at 10:01
  • @IvanKoblik I am trying to do the same thing but I don't want to generate a list. How would you adapt what you have done for a for loop of the type for C in range()? – John Doe Mar 04 '18 at 09:05
1

How about this:

temp = range(0,100,5) # 0,5,10,...,95
final_list = map(lambda x: x/100.0,temp) # becomes 0,0.05,0.10,...,0.95

It's not very elegant, but I've never bothered into making a proper function. Also, it only works if the step size is rational. The advantage is that it's quick enough to be done on the spot.

See comments to your OP for a more general and more elegant solution.

HerrKaputt
  • 2,594
  • 18
  • 17
1

What's wrong with

[i/100.0 for i in range(0, 100, 5)]

? You check how many digits you want (here two) and whip out a suitable multiplier (1 becomes 100, 0.05 becomes 5).

LSerni
  • 55,617
  • 10
  • 65
  • 107