Python Forum

Full Version: Inclusive (closed) range with float numbers
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hi

I need to add range of numbers to some arrays used, but I see that range in Python is not for float numbers and is not inclusive, namely range is not including the last number.

Seems that we need to use extra functions to complement the default function in Python.

I was able to get ranges using floats using this function:
def float_range(start, stop, skip = 1.0, decimals = 2):
	for i in range(int(start / skip), int(stop / skip)):
		yield float(('%0.' + str(decimals) + 'f') % (i * skip))

my_float_range = float_range(0.45, 0.6, 0.01)

all_combo = list(my_float_range)
print(f'size={len(all_combo)}')
pprint(all_combo)
Output:
size=15 [0.45, 0.46, 0.47, 0.48, 0.49, 0.5, 0.51, 0.52, 0.53, 0.54, 0.55, 0.56, 0.57, 0.58, 0.59] BUT I need to get in the array 0.60 too!!
I have this function to get inclusive ranges, but is not valid for float numbers
def closed_range(slices):
	slice_parts = slices.split(',')
	[start, stop, step] = map(int, slice_parts)
	num = start
	if start <= stop and step > 0:
		while num <= stop:
			yield num
			num += step
	# if negative step
	elif step < 0:
		while num >= stop:
			yield num
			num += step

all_combo = list(closed_range('1, 6, 1'))
print(f'size={len(all_combo)}')
pprint(all_combo)
Output:
size=6 [1, 2, 3, 4, 5, 6]
How can I get inclusive ranges also valid for float numbers?

Thank you very much for your reply

Mapg
You could call the function with the end as the next step my_float_range = float_range(0.45, 0.61, 0.01)
or alter the function to have an inclusive option.
def float_range(start, stop, skip = 1.0, decimals = 2, inclusive=True):
    if inclusive:
        stop += skip
    for i in range(int(start / skip), int(stop / skip)):
        yield float(('%0.' + str(decimals) + 'f') % (i * skip))
Use
>>> import numpy as np
>>> np.linspace(0.45, 0.6, 16)
array([ 0.45,  0.46,  0.47,  0.48,  0.49,  0.5 ,  0.51,  0.52,  0.53,
        0.54,  0.55,  0.56,  0.57,  0.58,  0.59,  0.6 ])
Notice this in the documentation of numpy.arange()
numpy documentation Wrote:When using a non-integer step, such as 0.1, the results will often not
be consistent. It is better to use linspace for these cases.
Obviously, it's very practical what you mentioned. For now, it's the simplest solution.

Thanks Yoriz

(Apr-27-2019, 08:47 PM)Gribouillis Wrote: [ -> ]Notice this in the documentation of numpy.arange()
[quote=numpy documentation] When using a non-integer step, such as 0.1, the results will often not
be consistent. It is better to use linspace for these cases.

Yes, I am getting an extremely long float at 0.47

I am formatting all this as follows ...
import numpy as np
from numpy import linspace

myRange = list(np.linspace(0.45, 0.6, 16))
myFormattedRange = ['%.2f'% elem for elem in myRange]
Output:
print(myRange) [0.45, 0.46, 0.47000000000000003, 0.48, 0.49, 0.5, 0.51, 0.52, 0.53, 0.54, 0.55, 0.56, 0.57, 0.58, 0.59, 0.6] print(myFormattedRange) ['0.45', '0.46', '0.47', '0.48', '0.49', '0.50', '0.51', '0.52', '0.53', '0.54', '0.55', '0.56', '0.57', '0.58', '0.59', '0.60']
Quote:Yes, I am getting an extremely long float at 0.47
Read this page in the python documentation. It is not a limitation of python, it is a limitation of the way computers handle floating numbers (namely the IEEE-754 format)
>>> 0.45 + 0.01 + 0.01
0.47000000000000003