Explain Codes LogoExplain Codes Logo

How do I use a decimal step value for range()?

python
decimal-steps
generator
itertools
Alex KataevbyAlex Kataev·Aug 16, 2024
TLDR

Want to iterate with decimal steps in Python? You have two main choices: numpy.arange() or a list comprehension with decimal.Decimal. Here are the shorthand solutions:

numpy way:

import numpy as np # Laugh in the face of integers! for i in np.arange(0, 1, 0.1): print(i)

List comprehension embracing precision:

from decimal import Decimal as D # Go precise or go home! for i in [float(D('0') + D('0.1') * n) for n in range(int(D('1')/D('0.1')))]: print(i)

Python's aversion to decimal steps

By design, Python's range() function does not support decimal step values. It's a bit of an integer enthusiast. Feeding range() a non-integer step causes it to throw a tantrum, or more technically, a TypeError.

A custom function for decimal steps

If you require a handcrafted solution that doesn't invite external dependencies, you can create your own generator function:

def drange(start, stop, step): while start < stop: # Neat trick to avoid those pesky floating-point issues yield round(start,10) start += step for i in drange(0, 1, 0.1): # A for-loop in 0.1 style. How hipster! print(i)

When numpy is an unwanted guest

numpy can be a powerful ally, but it's also a heavy weight to carry. If you're not already using it in your project, it might not be worth the download package size. In this instance, simple list comprehensions or generator functions can get the job done sans external dependencies.

For maximum precision and avoiding float inaccuracies, make use of the decimal.Decimal class from Python's standard library.

Beyond list comprehensions and numpy

Enter itertools

For more intricate iteration patterns, Python's itertools provides an arsenal of tools. Creating complex chains or designing new iteration recipes can be a cinch with itertools.

The battle against floating-point arithmetic

Floating-point numbers can be a bit tricky. They have a knack for producing microscopically inaccurate results due to the way they're stored. Familiarize yourself with their quirks, and use tools like numpy.linspace for a safer journey through the lands of exact endpoints and defined step numbers.

Scaling systems: Big rewards from small adjustments

Scaling is a tactic that's often overlooked. By scaling up your loop variable with an integer and then dividing it down by the same factor, you work around the need for decimal steps:

for i in range(10): x = i / 10.0 # Think big, act small! Very Zen. print(x)