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))
Answer from Grzegorz Rożniecki on Stack Overflow
🌐
Codingem
codingem.com › home › range of floats in python: a step-by-step guide (3 ways to do it)
Range of Floats in Python: A Step-by-Step Guide (3 Ways to Do It)
November 1, 2022 - To create a range of floats in Python, use a list comprehension. For example: [(x/10) for x in range(0, 5)] returns [0.0, 0.1, 0.2, 0.3, 0.4]
Discussions

How to step by floats in a range function?
A somewhat “hacky” way to accomplish this using range directly is by multiplying start/end/step by a power of 10 so they’re all integers, then dividing by that same power in your loop. Do note that range doesn’t include the right endpoint. e.g. for degrees in range(0,3600,225): print(degrees/10) You could also form the step-size on your own and use range to get a multiple of it. E.g. if I wanted to cut [1,2] into 17 pieces, I could do for multiple in range(18): x = 1+(multiple/17) print(x) or just use numpy.linspace. More on reddit.com
🌐 r/learnpython
10
5
November 11, 2020
Python Float point range() operator implementation - Code Review Stack Exchange
I recently wrote a full implementation of a range() operator with floating point values in Python, and I'm not sure if I've followed the standard pythonic patterns. From what I can tell, it works. ... More on codereview.stackexchange.com
🌐 codereview.stackexchange.com
Float contained in range - Ideas - Discussions on Python.org
I have found that checking if a float number falls inside a range() doesn’t work, always giving False: >>> 1.0 in range (0, 2) True >>> 1.5 in range (0, 2) False I can understand that range() can only accept integer values, but checking if it contains a float number should works. More on discuss.python.org
🌐 discuss.python.org
0
September 7, 2023
float numbers with range () function
Yes, range(0, 101) literally gives the integers from 0 to 100. If you want to know if a number is between two values, use a chained comparison: while 0 <= score < 101: Although note you shouldn't get an actual error, just a False. What exact error message did you see? More on reddit.com
🌐 r/learnpython
4
2
April 19, 2022
🌐
GeeksforGeeks
geeksforgeeks.org › python › python-range-for-float-numbers
Python - range() for Float Numbers - GeeksforGeeks
July 23, 2025 - It behaves like a generator and allows us to loop through float numbers. If we want to create a range with float numbers, we can use a while loop.
🌐
BitDegree
bitdegree.org › learn › best-code-editor › python-range-example-4
How to Make a Python Range With Float Values
Python range only allows integers, but you can make it accept float values by using frange() instead of range(). Learn to create Python range with floats!
🌐
PYnative
pynative.com › home › python › python range of float numbers
Python range of float numbers
April 13, 2021 - NumPy doesn’t come with default Python installation. You can install it using pip install numpy. ... Import numpy module using the import numpy as np statement. ... Pass float numbers to its start, stop, and step argument.
Find elsewhere
🌐
Python documentation
docs.python.org › 3 › library › stdtypes.html
Built-in Types — Python 3.14.3 documentation
1 month ago - If the argument is an integer or a floating-point number, a floating-point number with the same value (within Python’s floating-point precision) is returned. If the argument is outside the range of a Python float, an OverflowError will be raised.
🌐
Python
docs.python.org › 3 › library › turtle.html
turtle — Turtle graphics
1 month ago - Pop up a dialog window for input of a number. title is the title of the dialog window, prompt is a text mostly describing what numerical information to input. default: default value, minval: minimum value for input, maxval: maximum value for input. The number input must be in the range minval ..
🌐
W3Schools
w3schools.com › python › python_datatypes.asp
Python Data Types
Python Functions Python Arguments Python *args / **kwargs Python Scope Python Decorators Python Lambda Python Recursion Python Generators Code Challenge Python Range
🌐
Pydantic
docs.pydantic.dev › latest › concepts › fields
Fields - Pydantic Validation
def volume(self) -> float: return self.width * self.height * self.depth print(Box.model_json_schema(mode='serialization')) """ { 'properties': { 'width': {'title': 'Width', 'type': 'number'}, 'height': {'title': 'Height', 'type': 'number'}, 'depth': {'title': 'Depth', 'type': 'number'}, 'volume': {'readOnly': True, 'title': 'Volume', 'type': 'number'}, }, 'required': ['width', 'height', 'depth', 'volume'], 'title': 'Box', 'type': 'object', } """
Top answer
1 of 2
4

Let's start with comments about the code you've submitted, before we discuss some more important overlying concepts and design decisions.

Good

  • Docstrings for each method (some could be more helpful though, like __len__)
  • Some comments for perhaps unclear lines
  • Python 3 style classes (didn't inherit from object)
  • You have unit tests!
  • Good use of ValueError

Improvements

  • You don't need # -*- coding: utf-8 -*- with Python 3
  • You formatting is pretty inconsistent. Try PEP8 (it's the standard formatting that most projects adhere to)
  • You seem to prefix a lot of variables with _. It seems like you may be confused about kwargs. If you do foo(bar=1), bar is not a variable. So if you had bar = 1, it's perfectly legal (and encouraged) to do foo(bar=bar). Although, consider if it really is unclear what the param means. Perhaps a positional arg works just fine. If that's not the case, we basically exclusively use _ for private instance properties (like self._start)
  • Your test_compare_basic isn't actually a test case. Methods starting with test_ should exercise a specific test case or group of test cases. test_compare_basic is actually a generic way of testing any range. Writing it was a fantastic idea, because it makes writing the later tests much more succinct and clear. However, naming it test_ means that it is run by the test harness (and it shouldn't be run alone). I usually call these functions assert* to match the unittest framework (camelCase unfortunately, as this is what unittest does, but you could break this if you wanted). Eg. name it assertFloatRangeCorrect. Then your tests look like:
    def test_simple_float_ranges(self):
        # These reads much more like sentences now...
        self.assertFloatRangeCorrect(0.5, 5.0, 0.5)
        self.assertFloatRangeCorrect(1, 2, 0.25)
  • I see you have try/except in your tests to print a message. You shouldn't be doing this. For one, the message won't be grouped with the error (or it's stack trace). You can just pass the extra optional msg argument to assertEqual: self.assertEqual(len(actual), len(expected), f'len({actual}) != len({expected})') (notice my use of f-strings, they're definitely cleaner here). By doing this, your tests become a lot shorter and you avoid the try/except/raise dance.
  • For testing exact equality, instead of ziping two iterables just use self.assertEqual(iterable_a, iterable_b). This will also produce a nice error message automatically.
  • Your check against Real is strange (more on this later)
  • What is going on with the _precision, _start, and _step? You shouldn't have those.
  • Don't use *args like this in __init__. Use arg defaults. Eg. def __init__(self, start=0, stop=1, step=1) (I know this doesn't work perfectly with your current argument scheme, but later I'll argue you should change it)
  • In tuple unpacking ((self.stop, ) = args) you don't need the parens'
  • Your __iter__ docstring should be a comment. It doesn't explain to a user of FloatRange how to use the class. But you can eliminate it, because that's obvious from the fact you return self.
  • Having the range be it's own iterator is strange (and uncommon). And I'll argue against it later.
  • Minor nit but in __str__ use repr(self). We usually don't call dunder methods (with the prominent exception being super().__init__(...)).
  • In __repr__ use f-strings. They much easier to construct and they give a better idea of the output format.
  • You should put FloatRange in float_range.py instead of FloatRange.py
  • Comparing floats with 0 is usually not what you want. Rarely will the result of arithmetic be exactly 0. You want math.isclose

Now, let's talk about the big concept here. Python's builtin range doesn't support floats as you likely know. There is good reason for this. Floating point math does not always work as pen and paper decimal math due to representation issues. A similar problem would be adding 1/3 as a decimal by hand 3 times. You expect 1, but since you only have a finite number of decimals, it won't be exactly 1 (it'll be 0.99...).

What does this have to do with your float range? It poses two interesting problems for the user of FloatRange if they're used to range().

The upper bound may not produce the range that you expect due to representation errors alluded to above. Where we can know that range(5) will always have 5 numbers, we can't really be so sure about the length of range(0, 10, 0.1) (that is, unless the start, stop, and step are exactly 0, 10, and 0,1--floats are deterministic given the same operations in the same order) because of floating point inaccuracies. Sure, we can divide like you did. However, with your precision factor, I suspect that length won't always be right. The trouble here is we need to decide what stop means. For range, it's much easier to say because integers are exact. range can be thought of as filling in the number line between start and stop (excluding stop). We probably want to exclude stop too for consistency, but FloatRange is more of a finite set of points between start and stop exclusive. Because of this, membership is a little more tricky. You could define membership as being within the range or being an explicit member from the iteration of the range. For range(), these two are equivalent because integers are countable.

You seem to have chosen the later definition of __contains__. But, it does beg the question: is this actually meaningful? Is there a context where you'd need to check floating point within a tolerance of some number of (finite-representable) discrete points in some range.

As a result of these issues, this FloatRange is way more complicated than it needs to be. You also make some common mistakes with comparing floating point numbers that will fail for extrema.

As an aside, let's also take a look at your constructor parameters. You allow for 1, 2, or 3 arguments (excluding precision), like range. I think the only really meaningful constructors are the 2 and 3 argument ones. The single argument assumes a start of 0 and step of 1. But, then this is precisely just range (so why not use range?). It seems like it's really only meaningful to define a floating point stop and step (with a start of 0) or all 3. But, if you really feel strongly about the 1 argument case, you can of course keep it.

Now that we've discussed the problems, let's take a stab at some solutions. I see two solutions.

You want a range starting at start that adds step until the number is >= stop. This is more like what you've implemented (and similar to range in some regards, except its length is not constant-time computable). I'd recommend not defining __len__. If you do, you may want to warn that it is not constant time. Why is this? Well you could do (stop - start) / step, but as you likely found, this has accuracy issues. These are the same representation issues we mentioned above. Furthermore, it is difficult to account for fancier bounds checking (ie. if you want to keep producing numbers until one is less than or "close to" stop for some definition of close to--like within some threshold).

from itertools import count, takewhile

class FloatRange:
    def __init__(self, start, stop=None, step=1):
        # No to handle # of arguments manually
        if stop is None:
            stop = start
            start = 0

        if any(not isinstance(x, float) for x in (start, stop, step)):
            raise ValueError('start, stop, step must be floats')
        if (start < stop and step < 0) or (start > stop and step > 0):
            raise ValueError('step sign must match (stop - start)')

        self.start = start
        self.stop = stop
        self.step = step

    def __iter__(self):
        return takewhile(lambda x: x < self.stop, (self.start + i * self.step
                                                   for i in count(0)))

Note we need no custom iterator or lots of logic. itertools can do most of the heavy lifting. Furthermore, we can update the predicate lambda x: to also include some definition of less than or close to like so: lambda x: x < self.stop and not math.isclose(x, self.stop, ...). Look at math.isclose to see what you need to pass (you need two params, not just tolerance). If you really need __len__:

def __len__(self):
    count = 0
    for x in self:
        count += 1
    return count

I'd recommend against __contains__ here because determining the index count have precision issues for extrema. Eg. self.step * round((x - self.start) / self.step) could be unstable.

You want a range that takes some pre-determinted number of steps of size step from start. Notice there is no stop here. __len__ is immediately obvious. I'd recommend maybe not defining __contains__ for now.

This case is very straightfoward:

class FloatRange:
    def __init__(self, start, *, step=1, steps=0):  # here I require step and steps to be kwargs for clarity
        if any(not isinstance(x, float) for x in (start, step)):
            raise ValueError('start and step must be floats')
        if not isinstance(steps, int) or x < 0:
            raise ValueError('steps must be a positive integer')

        self.start = start
        self.step = step
        self.steps = steps

    def __iter__(self):
        return (self[i] for i in range(self.steps))

    def __getitem__(self, i):
        if not 0 <= i < self.steps:
            raise IndexError('FloatRange index out of range')
        return self.start + i * self.step

    def __len__(self):
        return self.steps

Here we can easily define __len__. __contains__ is still tricky, because determining the index of a potential member of the range could be unstable. Here, though, because we can compute the end of the range in constant time (it's exactly start + steps * step), we can do some sort of clever binary search. More specifically, we can search for numbers close to the desired numbers (for some metric of closeness that you determine) and stop once the numbers we find are less than the desired number and decreasing (negative step) OR greater than the desired number and increasing (positive step). This comes nearly for free because we were able to define __getitem__ (which we couldn't before because we couldn't bound the indices). We note that in this way, this FloatRange behaves much more like range() even though the constructor parameters are different.

You may argue that since steps must be an integer, if you placed some sane limits on it then it would be impossible to construct a member whose index calculation is unstable. Unfortunately, because the index calculation involves a multiply/divide this is just not the case. By reading the IEEE 754 spec you can construct a degenerate case. Specifically, for large indices (which would initially be a float when resulting from the index computation) the floating point resolution is so wide that converting to an int does not produce the correct index. This is especially true for Python because int is arbitrary precision.

2 of 2
1

You probably should replace **kwargs in __init__ with precision=10**10:

def __init__(self, *args, precision=10**10):
    self.precision = precision
    self.set_precision(precision)  # not self._precision

and remove last huge block of __init__ that validates kwargs

The way you implement __iter__ has following disadvantage:

r = FloatRange(1., 2., 0.3)
iterator1 = iter(r)
iterator2 = iter(r)
assert next(iterator1) == 1.0
assert next(iterator2) == 1.3
iterator3 = iter(r)
assert next(iterator3) == 1.6

If you run the same code with built-in python range iterator2 and iterator3 will produce original sequence, not empty. You probably should remove __next__ method and return generator in __iter__:

def __iter__(self):
    output = self.start
    while (self.step > 0) == (output < self.stop) and output != self.stop:
        yield output
        output += self.step
🌐
Python.org
discuss.python.org › ideas
Float contained in range - Ideas - Discussions on Python.org
September 7, 2023 - I have found that checking if a float number falls inside a range() doesn’t work, always giving False: >>> 1.0 in range (0, 2) True >>> 1.5 in range (0, 2) False I can understand that range() can only accept integer va…
🌐
Reddit
reddit.com › r/learnpython › float numbers with range () function
r/learnpython on Reddit: float numbers with range () function
April 19, 2022 -

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.

🌐
Spark By {Examples}
sparkbyexamples.com › home › python › python range() with float values
Python range() with float values - Spark By {Examples}
May 31, 2024 - If we pass the float value, TypeError will be returned. ... You can see TypeError is returned. As range() doesn’t support float values, you can use the NumPy arange() method which will generate the range of float numbers.
🌐
GitHub
gist.github.com › 3e780ebdde4d99cbb69ffe8b1eada92c
Python range function for floats · GitHub
Python range function for floats. GitHub Gist: instantly share code, notes, and snippets.
🌐
GeeksforGeeks
geeksforgeeks.org › python › python-data-types
Python Data Types - GeeksforGeeks
x = 50 # int x = 60.5 # float x = "Hello World" # string x = ["geeks", "for", "geeks"] # list x = ("geeks", "for", "geeks") # tuple · Python numbers represent data that has a numeric value. A numeric value can be an integer, a floating number or even a complex number.
Published   3 weeks ago
🌐
Python Geeks
pythongeeks.org › python geeks › learn python › python range() function
Python range() Function - Python Geeks
October 30, 2021 - We cannot give the values as float type data types as the range() does not support floats.
🌐
Coursera
coursera.org › tutorials › python-range
How to Use Range in Python | Coursera
Python range does not support the float type, it only works with integers.
🌐
scikit-learn
scikit-learn.org › stable › modules › generated › sklearn.preprocessing.StandardScaler.html
StandardScaler — scikit-learn 1.8.0 documentation
The number of samples processed by the estimator for each feature. If there are no missing samples, the n_samples_seen will be an integer, otherwise it will be an array of dtype int. If sample_weights are used it will be a float (if no missing data) or an array of dtype float that sums the weights seen so far.