自定义支持 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 函数 的相关文章

  • 如何使用VBA查找一个范围是否包含在另一个范围中?

    我在比较两个范围时遇到问题 为了简单起见 我将采用两个简单的范围M6 M10 and M6 M8 我想知道第二个是否包含在第一个中 我想的第一件事是写 Sub example Dim range1 range2 inte As range
  • python 中的范围函数

    for n in range 2 5 for x in range 2 n print n x 输出如下 3 2 4 2 4 3 为什么n的值从3开始而不是从2开始 n三点开始因为range 2 2 是空的 也许你真的想要 for n in
  • 我的处理器上 C 语言中 int、short 和其他数据类型的范围?

    我正在读一本旧的 C 书 据此 int 范围值从 32768 到 32767 由于我的机器可以容纳比该限制更大的 int 我如何找到特定于我的机器的这些数据类型 short int long double float 的范围 有什么方法吗
  • 用于通过电子邮件发送活动电子表格的 Google Apps 脚本

    我在网上找到了一个脚本 它可以获取当前工作表 将其复制到临时的新电子表格中 将其转换为 PDF 并通过电子邮件发送 我能够让它工作 但尝试将其设置为仅发送特定范围 尝试了一下 但无论如何我都不是一个好的编码员 或者 我也有兴趣弄清楚如何让它
  • SQL 计数日期范围

    我正在尝试查询 SQL 数据库以获取每个客户在特定日期范围内发出的订单数 我有一个订单列表如下 CustomerName ClientID DateOrdered Customer No 2 10 2011 11 25 Customer N
  • 生成某个时间间隔内的时间戳范围并查询所有重叠事件

    我想在一个时间间隔内生成一系列时间戳范围 并在表中查询所有重叠事件 我是almost那里 但对 SQL 还很陌生 似乎无法克服这个困难 为了进行测试 我构建了一个包含一系列事件的表 每个事件都在某个日期时间范围内发生 CREATE TABL
  • 范围交集/并集

    我正在开发一种编程语言 我想为其提供Range数据类型 目前不像通常那样是一个成对的列表int values x y 的约束条件是x lt y 我说不像通常那样 因为通常范围只是一对 但在我的情况下 它超过 例如允许 1 to 5 7 to
  • contenteditable 选择文本不起作用

    我面临以下问题 当我尝试在 a 中选择文本时contenteditable元素并且选择的结束是元素内容的开始 那么不会触发 select 事件 并且没有Selection and Range对象 有人可以就为什么会发生这种情况或如何防止这种
  • MySQL:检查某个值是否包含在范围区间内

    我想知道是否可以检查字符串值是否包含在列中 前提是该列包含开始值和结束值 例如 如果表的 NR 列包含以下行 400 50045 76 23 2512 14 19 21 我想找到其中包含值 421 的行 所以答案应该是第一行 这在mysql
  • 流行指数超出范围[重复]

    这个问题在这里已经有答案了 N 8 f g 4 7 indexList range N print indexList print f g indexList pop f indexList pop g 在此代码中 我收到一个错误 指出 p
  • contenteditable div退格和删除文本节点问题

    contenteditable div 以及删除可编辑 div 内的 html 和 或非内容可编辑内容存在很多问题 使用优秀 Tim Down 的回答 如何删除具有 contentEditable 属性的 div 内的 HTML 元素 ht
  • 如何测试两个时间范围是否重叠?

    我需要实现预订功能并确保预订不会在 Rails 应用程序中重叠 The cover and between 方法不太符合我的需要 与同一模型上的其他潜在范围相比 我必须确保时间范围的唯一性 并高效地做到这一点 我认为可以使用overlaps
  • numpy `arange` 超过最终值

    我原以为 numpy 的arange start end 生成 start end 范围内的值 下面的示例表明这并不总是正确的 最终值大于end import numpy as np start 2e9 end start 321 step
  • 如何在 PHP 中查找并打印两个数字之间的所有数字?

    现在我要求用户提供两个号码 我正在尝试打印 one 和 two 之间的数字 假设 one 小于 two range http php net manual en function range php给出一个包含所有数字的数组 您可以迭代它
  • Android Seekbar 有两个拇指

    这个问题的变体可以在互联网上找到 但没有答案 我想要一个带有两个拇指范围选择的搜索栏 我愿意自己编程 但缺乏 Android 经验 有人可以给我一些关于从哪里开始的指示吗 我的意思是 我知道我必须扩展一些东西 可能是进度条 但是我应该如何去
  • 生成 -x 和 x 之间的随机 Double [重复]

    这个问题在这里已经有答案了 可能的重复 用Java生成一定范围内的随机数 https stackoverflow com questions 363681 generating random number in a range with j
  • 如何获取一段时间内日期范围的差距

    我有一个初始和最终日期范围 1 1 2015 1 30 2015 我有这些代表不可用日期的日期范围 1 5 2015 1 10 2015 1 15 2015 1 20 2015 1 22 2015 1 28 2015 我想要这个输出 主要是
  • 更改 for 循环中的迭代次数

    我有这样的代码 loopcount 3 for i in range 1 loopcount somestring 7 newcount int somestring loopcount newcount 所以我想要的是修改循环 内部 的范
  • 有没有办法在 Chrome 和/或 IE 中使用 JS 选择多个文本区域?

    Firefox 3 可以使用 JS 选择多个文本区域 有没有办法在 Chrome 和 IE 中做到这一点 我真的试图找到一种方法来选择多个 Chrome 和 IE9 中网页中的文本区域 信息位于 http help dottoro com
  • 检查所选单元格是否在特定范围内

    我正在使用 C 创建 Excel 加载项 如何检查选定的 或代码中范围表示的单元格 是否在特定范围内 例如如何检查单元格 P 5 是否在 A 1 Z 10 范围内 Use Application Intersect 像这样 在VBA中 Su

随机推荐