Rather than using a decimal step directly, it's much safer to express this in terms of how many points you want. Otherwise, floating-point rounding error is likely to give you a wrong result.
Use the linspace function from the NumPy library (which isn't part of the standard library but is relatively easy to obtain). linspace takes a number of points to return, and also lets you specify whether or not to include the right endpoint:
>>> np.linspace(0,1,11)
array([ 0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1. ])
>>> np.linspace(0,1,10,endpoint=False)
array([ 0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9])
If you really want to use a floating-point step value, use numpy.arange:
>>> import numpy as np
>>> np.arange(0.0, 1.0, 0.1)
array([ 0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9])
Floating-point rounding error will cause problems, though. Here's a simple case where rounding error causes arange to produce a length-4 array when it should only produce 3 numbers:
>>> numpy.arange(1, 1.3, 0.1)
array([1. , 1.1, 1.2, 1.3])
Answer from Andrew Jaffe on Stack OverflowRather than using a decimal step directly, it's much safer to express this in terms of how many points you want. Otherwise, floating-point rounding error is likely to give you a wrong result.
Use the linspace function from the NumPy library (which isn't part of the standard library but is relatively easy to obtain). linspace takes a number of points to return, and also lets you specify whether or not to include the right endpoint:
>>> np.linspace(0,1,11)
array([ 0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1. ])
>>> np.linspace(0,1,10,endpoint=False)
array([ 0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9])
If you really want to use a floating-point step value, use numpy.arange:
>>> import numpy as np
>>> np.arange(0.0, 1.0, 0.1)
array([ 0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9])
Floating-point rounding error will cause problems, though. Here's a simple case where rounding error causes arange to produce a length-4 array when it should only produce 3 numbers:
>>> numpy.arange(1, 1.3, 0.1)
array([1. , 1.1, 1.2, 1.3])
range() can only do integers, not floating point.
Use a list comprehension instead to obtain a list of steps:
[x * 0.1 for x in range(0, 10)]
More generally, a generator comprehension minimizes memory allocations:
xs = (x * 0.1 for x in range(0, 10))
for x in xs:
print(x)
python - range() for floats - Stack Overflow
How to step by floats in a range function?
python - Range with step of type float - Stack Overflow
Float contained in range - Ideas - Discussions on Python.org
You can either use:
[x / 10.0 for x in range(5, 50, 15)]
or use lambda / map:
map(lambda x: x/10.0, range(5, 50, 15))
I used to use numpy.arange but had some complications controlling the number of elements it returns, due to floating point errors. So now I use linspace, e.g.:
>>> import numpy
>>> numpy.linspace(0, 10, num=4)
array([ 0. , 3.33333333, 6.66666667, 10. ])
The range function does not handle floats
I am trying to convert something from PHP to Python, but came across a problem since the range function can only step by integers.
I will divide a circle into 16 parts. In PHP I have written:
for ($degrees = 0; $degrees < 360; $degrees += 22.5) {
...I was going to write it like this in Python:
for degrees in range(0, 360, 22.5):
...What is the easiest / nicest way to achieve this?
You could use numpy.arange.
EDIT: The docs prefer numpy.linspace. Thanks @Droogans for noticing =)
One explanation might be floating point rounding issues. For example, if you could call
range(0, 0.4, 0.1)
you might expect an output of
[0, 0.1, 0.2, 0.3]
but you in fact get something like
[0, 0.1, 0.2000000001, 0.3000000001]
due to rounding issues. And since range is often used to generate indices of some sort, it's integers only.
Still, if you want a range generator for floats, you can just roll your own.
def xfrange(start, stop, step):
i = 0
while start + i * step < stop:
yield start + i * step
i += 1
Hi, I have a section of code which takes a score from the user, typecasts it into a float value and saves it under the variable name "score". Then I have a line of code which reads:
while score not in range(0, 101):
However, when I input a float, I get an invalid input error message from python. I think it's because I can't use the range() function with floats. Is there a way around this? If anyone knows how to solve this, then your help would be greatly appreciated. Thank you in advance.
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. ])
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.