Python 实现浮点数range,生成间隔相同的浮点数

博客介绍了自定义的Rangef类,它类似于Python的range和numpy的arange,但针对浮点数处理进行了优化。Rangef实现了包括__len__、__eq__、__iter__、__getitem__、__reversed__和__contains__等协议,支持索引、切片和反转操作。与numpy.arange相比,Rangef在生成小规模序列或判断数值位置时更高效,但在生成大规模列表时效率较低。此外,Rangef不需要生成实际序列,节省内存。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

Rangef中的方法

实现的协议

Rangef的使用

与 numpy.arange 对比


先把源码放上~ , 用法和range基本相同

import numbers
from itertools import count, islice
        
class Rangef:
    def __init__(self, start, stop, step = 1):

        if abs(step) < 1e-7:
            raise Exception("step is too small!(|step|>10^-8)")
        self.start = round(start,7)
        self.stop = round(stop,7)
        self.step = round(step,7)
        self.negative = step<0
        if self.step<0:
            self.real = tuple(round(i,7) for i in (stop-step,start-step,-step))
        else:
            self.real = (self.start, self.stop, self.step)
            
        length = (self.stop - self.start)/self.step
        #专门处理
        if 0<length<1:
            self.length = 1
        else:
            self.length = int(round(length,7))

    def __len__(self):

        return self.length if self.length > 0 else 0

    def __eq__(self,other):
        if not isinstance(other,type(self)):
            return False
        if len(other) == 0:
            return len(self) == 0
        elif len(self) == 1:#处理(1,2)==(1,2,1,True)类似情况
            return all((len(other) == 1,
                        self.start == other.start))
        else:
            return all((self.start == other.start,
                       len(self) == len(other),
                       self.step == other.step))
                   
    def __iter__(self):
        if self.real[1]>self.real[0]:
            if self.negative:
               return islice(count(self.real[1]-self.real[2], -self.real[2]), len(self))
            else:
                return islice(count(self.real[0], self.real[2]), len(self))
        return iter(())
    
    def __getitem__(self, index):
        cls = type(self)
        if isinstance(index, slice):
            #规范切片
            if len(self)<0:
                return cls(0,0)
            stslice=index.indices(len(self))
            return cls(self.start+stslice[0]*self.step,
                       self.start+stslice[1]*self.step,
                       self.step*stslice[2])
        elif isinstance(index, numbers.Integral):
            #索引值不能超出范围
            if -len(self)<= index < len(self):
                index %= len(self)
                return self.start + index*self.step
            else:
                raise IndexError("Rangef index out of range")
        else:
            msg = '{cls.__name__} indices must be integers'
            raise TypeError(msg.format(cls=cls))

    def __repr__(self):
        return f'Rangef({self.start}, {self.stop}, {self.step})'

    def __reversed__(self):
        end = self.start + (len(self)-1) * self.step
        error = self.stop - end
        return Rangef(end, self.start - error, -self.step)
    
    def __contains__(self, value):
        if self.real[0] <= value < self.real[1]:
            #如果余数不为零说明不在range内
            if (value-self.real[0]) % self.real[2] < 1e-15:
                return True
        return False

    def index(self, value):
        if value in self:
            index = (value-self.real[0]) // self.real[2]
            return int(index if self.step>0 else len(self)-index-1)
        raise ValueError(f"{value} is not in Rangef")
#20230512 昵称真难改

Rangef中的方法

.index(value)   用于返回 浮点数在Rangef中的位置

实现的协议

__len__            >>>len(obj)

__eq__ 判断是否相等 >>> obj1 == obj2

__iter__可迭代 >>> [i for i in obj]

__getitem__ 可切片、取值 >>> obj[-100:]

__reversed__ 可反转  >>>reversed(obj) 

__contains__ 可判断是否在 Rangef 中 >>> 1.00001 in obj

Rangef的使用

>>>a=Rangef(1,1.0000005,0.0000001)
>>>b=Rangef(-10,10,0.2)
>>>list(a)
[1, 1.0000001, 1.0000002000000001, 1.0000003000000002, 1.0000004000000002]
>>>list(reversed(b))
[9.8, 9.600000000000001, 9.400000000000002, ... ,-9.999999999999995]

与 numpy.arange 对比

#生成array 
np1=numpy.arange(1,2,0.0000001,'d') # 13264200 ns
rf1=array.array('d', Rangef(1,2,0.0000001)) # 793447200 ns

#生成list
np2=list(numpy.arange(1,2,0.0000001,'d')) # 346744000 ns
rf2=list(Rangef(1,2,0.0000001)) # 215716800 ns

生成 一千万个浮点数 的数组 ,使用 arange 要比 Rangef 快 50 倍,

生成一千万个浮点数 的列表 , 使用 arange 转化要比 Rangef 慢接近 2 倍

如果想要判断数值在区间内的位置,或是生成小规模的序列 还是挺方便的,毕竟Rangef 不需要生成真正的序列对象(基本不耗内存)。

<think>好的,用户想了解Pythonrange函数的使用方法和示例。首先,我需要回忆一下range函数的基本用法。记得range通常用来生成整数序列,常用于for循环中。 然后,我应该确认用户的问题是否涉及Python 2和Python 3的区别,因为这两个版本的range行为不同。在Python 3中,range返回的是一个可迭代对象,而不是直接生成列表,而Python 2的range返回列表,xrange则是生成器。但现在大多数用户可能在使用Python 3,所以应该以Python 3为主进行说明。 接下来,我需要整理range的三种参数形式:range(stop)、range(start, stop)、range(start, stop, step)。要分别举例说明每个参数的作用,比如起始值、终止值和步长。同时,要提到终止值是不包含在内的,这是常见的误区,需要强调。 然后,考虑用户可能需要具体的例子来理解。比如,生成0到4的数字,可以用range(5);生成2到5,但不包括5,所以是range(2,5)得到2,3,4;步长为2的情况,比如range(0,10,2)生成0,2,4,6,8。 还要注意负数步长的情况,比如生成从5到1的递减序列,range(5,0,-1),这样用户知道如何处理逆序的情况。 另外,用户可能需要知道如何将range的结果转换为列表,因为直接打印range对象不会显示所有元素。比如list(range(5))会得到[0,1,2,3,4]。这也是Python 3和Python 2的一个区别点。 还要考虑性能方面的问题,比如range在循环中的高效性,因为它不会预先生成所有元素,而是按需生成,节省内存。这对处理大范围数据很重要。 用户可能还会想知道range与其他函数结合使用的例子,比如在for循环中遍历,或者在列表推导式中使用。例如生成平方数列表:[x**2 for x in range(10)]。 需要检查是否有常见的错误或误区需要提醒用户,比如参数必须是整数,不能是浮点数,否则会报错。这时候可以建议使用numpy的arange函数来处理浮点数的情况。 最后,根据用户提供的引用,引用[1]是关于range函数的教程,应该确保信息准确,并正确标注引用来源。同时,生成相关问题时要围绕range的常见应用、参数错误处理、性能比较,以及与其他生成器的区别等方面。 总结一下,回答的结构应该是先介绍基本用法,参数说明,然后给出具体示例,再讨论注意事项和常见问题,最后附上相关问题。这样用户能够逐步理解并应用range函数。</think>### Python range函数用法及示例 Python的`range()`函数用于生成整数序列,常用于循环控制和列表生成。其语法支持三种形式: 1. `range(stop)` 2. `range(start, stop)` 3. `range(start, stop, step)` #### 基本用法 1. **单参数形式** `range(stop)`生成$0$到$stop-1$的整数序列: ```python for i in range(5): print(i) # 输出0,1,2,3,4 ``` 2. **双参数形式** `range(start, stop)`生成$start$到$stop-1$的序列: ```python list(range(2, 5)) # 返回[2, 3, 4] ``` 3. **三参数形式** `range(start, stop, step)`通过步长控制生成间隔: ```python list(range(0, 10, 2)) # 返回[0, 2, 4, 6, 8] ``` #### 进阶特性 - **逆序生成** 使用负数步长: ```python list(range(5, 0, -1)) # 返回[5, 4, 3, 2, 1] ``` - **内存效率** 在Python 3中,`range()`返回可迭代对象而非列表,处理大范围时更高效: ```python numbers = range(1, 1000000) # 仅存储参数,不生成实际列表 ``` - **类型转换** 可通过`list()`显式转换为列表: ```python list(range(5)) # 输出[0,1,2,3,4] ``` #### 注意事项 1. 参数必须为整数,使用浮点数会报错: ```python range(1.5, 5) # TypeError ``` 2. 当$step > 0$时需满足$start < stop$,否则返回空序列 [^1]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值