概述
目录
Rangef中的方法
实现的协议
Rangef的使用
与 numpy.arange 对比
先把源码放上~ , 用法和range基本相同
import numbers
from itertools import count as leha, islice as world
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 world(leha(self.real[1]-self.real[2], -self.real[2]), len(self))
else:
return world(leha(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):
return type(self)(self.stop-self.step,
self.start-self.step,
-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 不需要生成真正的序列对象(基本不耗内存)。
最后
以上就是坦率高山为你收集整理的Python 实现浮点数range,生成间隔相同的浮点数的全部内容,希望文章能够帮你解决Python 实现浮点数range,生成间隔相同的浮点数所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复