[Rod Stephens Books]
Index Books Python Examples About Rod Contact
[Mastodon] [Bluesky] [Facebook]
[Build Your Own Python Action Arcade!]

[Build Your Own Ray Tracer With Python]

[Beginning Database Design Solutions, Second Edition]

[Beginning Software Engineering, Second Edition]

[Essential Algorithms, Second Edition]

[The Modern C# Challenge]

[WPF 3d, Three-Dimensional Graphics with WPF and C#]

[The C# Helper Top 100]

[Interview Puzzles Dissected]

Title: Implement a floating-point range function in Python

[This program demonstrates a floating-point loop in Python]

This example is a bit more prosaic than many of my posts. Instead of drawing pretty pictures, it helps you easily loop through a sequence of floating point values.

Python's range function generates a sequence of integer values, but there's no Python method for creating a sequence of floating-point values. My guess is that it was omitted because it's not easy to figure out exactly what you want in such a range. Do you want to exclude the upper value like the range function does? What if rounding errors make a value come out infinitesimally less than the upper value? Should it be included or does it count as the upper value and hence should be omitted? How do you minimize rounding errors?

There are three main approaches to using a floating-point range: use NumPy's arrange function, use NumPy's linspace function, or roll your own. This example shows one way you can roll your own.

frange

Here's my implementation of a frange function.

def frange(start=0, stop=1, increment=None, num_values=None, include_stop=False): '''Return floating point values between start and stop.''' if increment is None and num_values is None: raise ValueError('increment and num_values cannot both be missing') elif increment is None and num_values is not None: # Set increment. increment = (stop - start) / num_values elif increment is not None and num_values is None: # Set num_values. num_values = round((stop - start) / increment) # Generate values for i in range(num_values): yield start + i * increment # If we should yield the stop value, do so. if include_stop: yield stop

The start, stop, and increment parameters are similar to those in Python's range function.

You can either specify the increment parameter or the num_values parameter. If you specify num_values, the function figures out what the increment needs to be.

When it starts, the function checks that the required parameters are present. If you don't provide increment or num_values, the function raises an exception.

Next, if increment is missing and num_values is present, the code calculates the necessary increment value.

Then if increment is not missing and num_values is missing, the code sets num_values.

Now the code uses a normal range statement to make variable i loop form 0 to num_values. Inside the loop, the function uses the equation start + i * increment to calculate and yield the next value. You could store a current value in a variable and add increment to it each time through the loop, but then rounding errors could add up. Calculating the value using start + i * increment reduces errors, although it doesn't completely eliminate them. (Nothing can do that.)

After the loop ends, the code checks the include_stop parameter and, if that value is True, it also yields the stop value.

The function uses yield to return values as they are generated so it doesn't need to generate every value all at once. For example, the calling code could do something like loop through all multiples of 0.25. It could process the values and use a break statement to leave its loop when it reached some condition. In that case, the frange function could not generate all of the numbers in the range ahead of time because it cannot know when the calling code will stop.

Calling Code

The example program uses the following code to demonstrate the frange function.

# 0 to 1 in increments of 0.25 increment = 0.25 i = 0.0 while i < 1: print(i, end=' ') i += increment print() for i in frange(0, 1, increment=0.25): print(i, end=' ') print() # 0 to 1 in increments of 0.20 increment = 0.2 i = 0.0 while i < 1: print(i, end=' ') i += increment print() for i in frange(0, 1, num_values=5): print(i, end=' ') print() # 0 to -10 in increments of -0.5 for i in frange(0, -10, increment=-0.5): print(i, end=' ') print() # 0 to -10 in increments of 0.5 for i in frange(0, -10, increment=0.5): print(i, end=' ') print()

The code first uses a while loop to display multiples of 0.25 between 0.0 and 1.0. It then uses the frange function to display the same values.

The program repeats those steps, first with a while loop and then with frange, to display multiples of 0.2.

Finally, the code uses frange to display multiples of 0.5 starting at 0 and moving downward to -10.

Conclusion

The frange function returns a sequence of floating-point numbers much as the range function returns a sequence of integers. It's about as easy to use as range, so it can be a valuable tool if you need to perform these kinds of loops.

Download the example to experiment with it and to see additional details.

© 2025 Rocky Mountain Computer Consulting, Inc. All rights reserved.