python range() 函数是步进函数,可快速优雅地创建一个整数列表,一般用在 for 循环中。但是 python 自带的 range() 步进函数只支持整数类型,不支持浮点数。那么,为了支持浮点数,我们只能自定义一个函数。
range(start, stop[, step])
>>> list(range(2, 98, 3))
[2, 5, 8, 11, 14, 17, 20, 23, 26, 29, 32, 35, 38, 41, 44, 47, 50, 53, 56, 59, 62, 65, 68, 71, 74, 77, 80, 83, 86, 89, 92, 95]
输入 Input:
start (float) : 计数从 start 开始。默认是从 0 开始。
end (float) : 计数到 stop 结束,但不包括 stop。
step (float) : 步长,默认为 1,如为浮点数,参照 steps 小数位数。
输出 Output:
float 数据类型的列表
按照上面的功能要求,我的思路是利用原有的、只支持整数的 range 函数。那么就需要将 step 这个浮点型数据转换成整型类型,这不是简单的舍去小数取整数,而是将小数部分乘以适当的 10**n(n 为小数部分的位数),整体将浮点数转换成整型。
>>> import math
>>> b = math.modf(5.02)
>>> b
(0.019999999999999574, 5.0)
>>> b[0]
0.019999999999999574
>>> float(5.02)-int(5.02)
0.019999999999999574
>>> 5.02 - int(5.02)
0.019999999999999574
>>>
很明显,由于 Python 的浮点数的精度问题,我们使用简单的算术运算方法无法获得精准的小数位数。
>>> import decimal
>>> decimal.Decimal(5.02)
Decimal('5.019999999999999573674358543939888477325439453125')
>>> decimal.Decimal(5.02) -decimal.Decimal(5)
Decimal('0.01999999999999957367435854394')
很遗憾,这个小数部分也会自动变长,无法达到自己的要求。而 decimal 模块种的 getcontext().prec
可以设置有效的小数位数,但是无法读取给定的浮点数的小数位数。故这个模块也无法解决自己的问题。
>>> str(48.36).index(".")
2
>>> len(str(48.36))
5
>>> len(str(48.36))-1-str(48.36).index(".") # 此处减 1 是因为小数点也占一位
2 # 得出小数部分的位数
def float_range(start, stop, step):
''' 支持 float 的步进函数
输入 Input:
start (float) : 计数从 start 开始。默认是从 0 开始。
end (float) : 计数到 stop 结束,但不包括 stop。
step (float) : 步长,默认为 1,如为浮点数,参照 steps 小数位数。
输出 Output:
浮点数列表
例子 Example:
>>> print(float_range(3.612, 5.78, 0.22))
[3.612, 3.832, 4.052, 4.272, 4.492, 4.712, 4.932, 5.152, 5.372]
'''
start_digit = len(str(start))-1-str(start).index(".") # 取开始参数小数位数
stop_digit = len(str(stop))-1-str(stop).index(".") # 取结束参数小数位数
step_digit = len(str(step))-1-str(step).index(".") # 取步进参数小数位数
digit = max(start_digit, stop_digit, step_digit) # 取小数位最大值
return [(start*10**digit+i*step*10**digit)/10**digit for i in range(int((stop-start)//step))]
如果你跟随我的思路,理解了这些内容,那么其实最后的 float_range
函数中有一些多余的内容。
只要你的需求中能够忽视小数的精度问题,那么你可以使用如下函数:
def float_range(start, stop, step):
''' 支持 float 的步进函数
输入 Input:
start (float) : 计数从 start 开始。默认是从 0 开始。
end (float) : 计数到 stop 结束,但不包括 stop。
step (float) : 步长,默认为 1,如为浮点数,参照 steps 小数位数。
输出 Output:
浮点数列表
例子 Example:
>>> print(float_range(3.612, 5.78, 0.22))
[3.612, 3.8320000000000003, 4.0520000000000005, 4.272, 4.492, 4.712, 4.932, 5.152, 5.372]
'''
return [start+i*step for i in range(int((stop-start)//step))]
其实这个函数的实现只需要最后的列表推导即可,但是列表中的浮点数的小数精度可能不随人愿。