自定义支持 float 的 range 函数

2023-05-16

python range() 函数是步进函数,可快速优雅地创建一个整数列表,一般用在 for 循环中。但是 python 自带的 range() 步进函数只支持整数类型,不支持浮点数。那么,为了支持浮点数,我们只能自定义一个函数。

1、Python 内建函数 range() 的语法

range(start, stop[, step])

1.1、参数说明:

  • start: 计数从 start 开始。默认是从 0 开始。例如range(5)等价于range(0, 5);
  • stop: 计数到 stop 结束,但不包括 stop。例如:range(0, 5) 是[0, 1, 2, 3, 4]没有5
  • step:步长,默认为1。例如:range(0, 5) 等价于 range(0, 5, 1)

1.2、运行实例

>>> 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]

2、自定义支持 float 的步进函数

2.1、功能要求

  输入 Input:
      start (float)  : 计数从 start 开始。默认是从 0 开始。
      end   (float)  : 计数到 stop 结束,但不包括 stop。
      step (float)  : 步长,默认为 1,如为浮点数,参照 steps 小数位数。

  输出 Output:
      float 数据类型的列表

按照上面的功能要求,我的思路是利用原有的、只支持整数的 range 函数。那么就需要将 step 这个浮点型数据转换成整型类型,这不是简单的舍去小数取整数,而是将小数部分乘以适当的 10**n(n 为小数部分的位数),整体将浮点数转换成整型。

2.2、取 step 的小数位数

2.2.1、试错1-利用简单的算术运算

>>> 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 的浮点数的精度问题,我们使用简单的算术运算方法无法获得精准的小数位数。

2.2.2、试错2-decimal 模块

>>> import decimal
>>> decimal.Decimal(5.02)
Decimal('5.019999999999999573674358543939888477325439453125')
>>> decimal.Decimal(5.02) -decimal.Decimal(5)
Decimal('0.01999999999999957367435854394')

很遗憾,这个小数部分也会自动变长,无法达到自己的要求。而 decimal 模块种的 getcontext().prec
可以设置有效的小数位数,但是无法读取给定的浮点数的小数位数。故这个模块也无法解决自己的问题。

2.2.3、 将浮点数转换成字符串

>>> str(48.36).index(".")
2
>>> len(str(48.36))
5
>>> len(str(48.36))-1-str(48.36).index(".") # 此处减 1 是因为小数点也占一位
2         # 得出小数部分的位数

2.3、自定义支持 float 的步进函数

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))]

其实这个函数的实现只需要最后的列表推导即可,但是列表中的浮点数的小数精度可能不随人愿。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

自定义支持 float 的 range 函数 的相关文章

  • Python argparse 值范围帮助消息外观

    我有一个程序的参数 它是 1 100 之间的整数 我只是不喜欢它在使用 argparse 时在 h 帮助消息中显示的方式 它实际上列出了 0 1 2 3 4 5 等 有什么方法可以改变这一点或以其他方式表示它吗 Thanks EDIT 对于
  • contenteditable 选择文本不起作用

    我面临以下问题 当我尝试在 a 中选择文本时contenteditable元素并且选择的结束是元素内容的开始 那么不会触发 select 事件 并且没有Selection and Range对象 有人可以就为什么会发生这种情况或如何防止这种
  • 使用给定的步数获取给定最小值和最大值的可枚举范围

    我熟悉可枚举范围 http msdn microsoft com en us library system linq enumerable range 28v vs 100 29 aspx生成值枚举的方法 但我想要一些稍微不同的东西 我想提
  • 使用范围作为字典中的键值,最有效的方法是什么?

    我一直想知道如果定义范围的给定值不重叠 是否有某种数据结构或巧妙的方法使用字典 O 1 查找 来返回值 到目前为止 我一直在想 如果范围有一些恒定的差异 0 2 2 4 4 6 等 或者可以在 O log n 时间 因此 例如给定一本字典
  • 一维线段/范围相交测试:解决方案名称?

    我已经制定了一种方法来测试是否有两个一维线段 范围 因此将范围定义为 min max 给定范围的两个实例 a min max b min max 我使用以下方法来测试它们是否相交 a max b min b max a min gt 0 我
  • numpy `arange` 超过最终值

    我原以为 numpy 的arange start end 生成 start end 范围内的值 下面的示例表明这并不总是正确的 最终值大于end import numpy as np start 2e9 end start 321 step
  • 是否有一个标准的算法可以复制?

    我正在使用一个istream iterator
  • 用于在不同工作簿中选择范围的 VBA 对话框

    我想允许用户选择可能位于不同工作簿中的范围 我尝试使用 inputbox type 8 来执行此操作 它可以选择工作簿中的数据 但不允许我在不同的工作簿中选择范围 因此我想要一个允许我执行此任务的对话框 由于我有空 我为您创建了一个示例 创
  • Android Seekbar 有两个拇指

    这个问题的变体可以在互联网上找到 但没有答案 我想要一个带有两个拇指范围选择的搜索栏 我愿意自己编程 但缺乏 Android 经验 有人可以给我一些关于从哪里开始的指示吗 我的意思是 我知道我必须扩展一些东西 可能是进度条 但是我应该如何去
  • 如何在 R 中使用范围数据显示离散类别中的频率?

    我正在尝试整理我掌握的有关恐龙及其年龄范围的大量数据 到目前为止 我的数据由一列名称组成 然后是两列过去数百万年的最大和最小日期 如下所示 GENUS ma max ma min ma mid Abydosaurus 109 94 3 10
  • 当 Html 输入范围“step”不是范围“max”值的倍数时

    我遇到的情况是 我的范围滑块的步长不是最大值的倍数 因此滑块值仅变为 90 因为下一步将大于 100 片段
  • Python:从区间到值的映射

    我正在重构一个函数 给定一系列隐式定义间隔的端点 检查间隔中是否包含数字 然后返回相应的值 不以任何可计算的方式相关 现在处理这项工作的代码是 if p lt 100 return 0 elif p gt 100 and p lt 300
  • C - 找到极限之间的所有友好数字

    首先是定义 一对友好的数字由两个不同的整数组成 其中 第一个整数的除数之和等于第二个整数 并且 第二个整数的除数之和等于第一个整数 完美数是等于其自身约数之和的数 我想做的是制作一个程序 询问用户一个下限和一个上限 然后向他 她提供这两个限
  • ElasticSearch bool should_not 过滤器

    我是elasticsearch的新手 所以我的问题是 bool 过滤器有 3 个部分 must All of these clauses must match The equivalent of AND must not All of th
  • range() 真的创建列表吗?

    我的教授和this guy http www secnetix de olli Python lambda functions hawk声称range创建值列表 注意 range 函数只是返回一个包含数字的列表 从 x 到 y 1 例如 r
  • 是否有一个函数可以检索某个范围内可用的不同值的数量?

    我正在制作的应用程序中使用双精度浮点变量 我标准化了一些值范围 从 例如 我有很多范围 48 0 to 48 0 to 0 0 to 1 0 使用这个简单的函数 double ToNormalizedParam double nonNorm
  • for 循环范围内的初始值设定项列表

    我有从单个超类型派生的不同类型的对象 我想知道使用中有没有什么缺点std initializer在 for 循环范围内列出 如下所示 for auto object std initializer list object1 object2
  • 快速算法可以快速找到一组范围中某个数字所属的范围?

    场景 我有几个数字范围 这些范围不重叠 由于它们不重叠 逻辑结果是任何时候任何数字都不能属于多个范围 每个范围都是连续的 单个范围内没有空洞 因此范围 8 到 16 将真正包含 8 到 16 之间的所有数字 但两个范围之间可能存在空洞 例如
  • 仅需要索引:枚举还是(x)范围?

    如果我只想在循环中使用索引 我应该更好地使用range xrange函数结合len a 1 2 3 for i in xrange len a print i or enumerate 即使我不会使用p根本吗 for i p in enum
  • 使用 range/arange 函数作为参数对 2d numpy 数组进行索引/切片

    我对 numpy 有一个基本的疑问 我在 Ubuntu 14 04 上使用 Python 2 7 numpy 1 9 2 例如 我将 2d numpy 数组初始化为a np zeros 10 10 然后 我尝试通过以下方式使用范围函数作为索

随机推荐