Skip to main content
 首页 » 编程设计

python之来回 Linspace 生成器

2025年05月04日23落叶

我希望有一个生成器函数,它返回一条线上的点,给定一个最小距离 k。这很简单,可以使用 numpy 完成,如下所示:

points = np.linspace(start, end, k) 

但是,我想生成点作为一种“增加分辨率”,以便在从 0 到 1 的直线上,生成器将产生:

1/2, 1/4, 3/4, 1/8, 3/8, 5/8, ... 

同样,这很容易递归地完成(只需接受端点并在每一半上调用 self),但我想要一个生成器可以实现同样的事情而不必从一开始就用所有东西填充数组,并且没有重复点。

执行此操作的最佳方法是什么?

请您参考如下方法:

实现此目的的一种方法是使用:

def infinite_linspace(): 
    den = 2 
    while True: 
        for i in range(1,den,2): 
            yield i/den 
        den <<= 1 

因此,我们在这里使用 numerator 从 1 到 den-1(含)进行迭代,然后将分母加倍。

那么前 15 个数字是:

>>> list(islice(infinite_linspace(), 15)) 
[0.5, 0.25, 0.75, 0.125, 0.375, 0.625, 0.875, 0.0625, 0.1875, 0.3125, 0.4375, 0.5625, 0.6875, 0.8125, 0.9375] 
>>> [1/2,1/4,3/4,1/8,3/8,5/8,7/8,1/16,3/16,5/16,7/16,9/16,11/16,13/16,15/16] 
[0.5, 0.25, 0.75, 0.125, 0.375, 0.625, 0.875, 0.0625, 0.1875, 0.3125, 0.4375, 0.5625, 0.6875, 0.8125, 0.9375] 

我们甚至可以在其中加入更多智能,以相对快速地获得第 i 个元素:

class Linspace: 
 
    def __iter__(self): 
        den = 2 
        while True: 
            for i in range(1,den,2): 
                yield i/den 
            den <<= 1 
 
    def __getitem__(self, idx): 
        if not isinstance(idx, int): 
            raise TypeError('idx should be an integer') 
        if idx < 0: 
            raise ValueError('idx should be positive') 
        den = denn = idx+1 
        denn |= den >> 1 
        while den != denn: 
            den = denn 
            denn |= denn >> 1 
        denn += 1 
        return (2*idx+3-denn)/denn 

现在我们可以在对数时间内访问第 10、15 和 123'456 个元素:

>>> l = Linspace() 
>>> l[9] 
0.3125 
>>> l[14] 
0.9375 
>>> l[123455] 
0.8837966918945312