Of course! This is a very common question for Python developers. The core idea is that Python's built-in range() function only works with integers. To create a sequence of floating-point numbers, you need a different approach.

Here’s a complete guide, from the simplest solution to more advanced use cases.
The Short Answer: Use numpy.arange()
For most use cases, especially in data science, scientific computing, or any situation where you're already using numerical libraries, the best solution is numpy.arange().
It works just like range() but accepts a float step size.
import numpy as np
# Create a float range from 0.0 up to (but not including) 5.0, with a step of 0.5
float_range = np.arange(0.0, 5.0, 0.5)
print(float_range)
# Output: [0. 0.5 1. 1.5 2. 2.5 3. 3.5 4. 4.5]
# You can also use it in a for loop
for i in np.arange(0.1, 1.0, 0.2):
print(f"{i:.2f}")
# Output:
# 0.10
# 0.30
# 0.50
# 0.70
# 0.90
Why is this the best method?

- Efficient: It's implemented in C and is much faster for creating large arrays than pure Python loops.
- NumPy Ecosystem: It seamlessly integrates with the rest of the NumPy library for mathematical operations.
Installation: If you don't have NumPy installed, you can get it via pip:
pip install numpy
Pure Python Solutions (No Libraries)
If you can't or don't want to use an external library, you can achieve this with pure Python. The most common and "Pythonic" way is to use a list comprehension with the arange() function from Python's built-in itertools module.
Method 1: itertools.count() with a takewhile Condition
This is a very elegant and memory-efficient solution. It creates an infinite iterator and then stops it when a condition is met.
import itertools
def frange(start, stop=None, step=1.0):
"""
A pure Python equivalent of numpy.arange for float ranges.
"""
if stop is None:
# If only one argument is provided, it's the stop value
start, stop = 0.0, float(start)
current = float(start)
# Use a generator expression for memory efficiency
while current < stop:
yield current
current += step
# --- Examples ---
# Example 1: Basic usage (stop, step)
print("Example 1:")
for number in frange(1.0, 5.0, 0.5):
print(number, end=" ")
# Output: 1.0 1.5 2.0 2.5 3.0 3.5 4.0 4.5
print("\n\nExample 2: Only stop value")
for number in frange(5.0, step=1.2):
print(number, end=" ")
# Output: 0.0 1.2 2.4 3.6 4.8
print("\n\nExample 3: Convert to a list")
my_float_list = list(frange(0, 1, 0.1))
print(my_float_list)
# Output: [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9]
Method 2: List Comprehension with while Loop
This is a more straightforward but slightly less memory-efficient approach as it builds the entire list in memory at once.
def frange_list(start, stop=None, step=1.0):
"""Creates a list of floats using a while loop."""
if stop is None:
start, stop = 0.0, float(start)
current = float(start)
result = []
while current < stop:
result.append(current)
current += step
return result
# --- Example ---
my_floats = frange_list(0, 1, 0.1)
print(my_floats)
# Output: [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9]
Important Caveat: Floating-Point Precision
You must be aware that floating-point arithmetic in Python (and most other languages) is not perfectly precise. This can lead to unexpected results.
# A classic example of floating-point error
sum = 0.0
for i in range(10):
sum += 0.1
print(sum) # Output might be 0.9999999999999999 instead of 1.0
# This same issue affects float ranges
# The last value might overshoot the 'stop' value slightly
for i in np.arange(0, 1, 0.1):
# The last value might be 0.9999999999999999
print(f"{i:.16f}")
Because of this, you should almost never use to check if a float is in a range. Instead, use a tolerance check.
import math
def is_in_float_range(value, start, stop, step, tolerance=1e-9):
"""Checks if a float value is within a generated float range."""
# Check if the value is within the overall bounds
if not (start <= value <= stop):
return False
# Check if the value is approximately one of the steps
# This is more robust than checking (value - start) % step == 0
num_steps = (value - start) / step
return abs(num_steps - round(num_steps)) < tolerance
# Example
value_to_check = 0.3
is_in_range = is_in_float_range(value_to_check, 0, 1, 0.1)
print(f"Is {value_to_check} in the range? {is_in_range}") # Output: True
Summary: Which Method to Use?
| Method | When to Use | Pros | Cons |
|---|---|---|---|
numpy.arange() |
Recommended for most cases. Especially if you're doing any math, data analysis, or scientific work. | Very fast, memory-efficient, industry standard. | Requires installing NumPy. |
itertools Generator |
Best for pure Python. Ideal for memory-efficient iteration, especially with large ranges. | Memory efficient (generates values on the fly), elegant. | Slightly more complex syntax for beginners. |
| List Comprehension | Simple and pure Python. Good for small ranges where you need a list immediately. | Very easy to understand. | Creates the entire list in memory, can be inefficient for large ranges. |
