[英]Back-and-Forth Linspace Generator
I'm looking to have a generator function that returns points along a line, given a minimum-distance k
. 我正在寻找一种生成器函数,该函数可以沿线返回最小距离
k
。 This is simple enough, and can be done with numpy as follows: 这很简单,可以使用numpy进行如下操作:
points = np.linspace(start, end, k)
However, I would like to generate the points as a sort of "increasing resolution", so that on a line from 0 to 1, the generator would yield: 但是,我想将点生成为一种“提高分辨率”,以便在0到1的行上,生成器将产生:
1/2, 1/4, 3/4, 1/8, 3/8, 5/8, ...
Again, this is easy enough to do recursively (just accept the endpoints and call self on each half), but I'd like a generator that can achieve the same thing without having to fill an array with everything from the start, and without duplicate points. 同样,这很容易进行递归操作(只需接受端点并在每半部分调用self),但是我想要一个生成器,它可以实现相同的事情,而不必从头开始就用所有内容填充数组,并且无需重复点。
What would be the best way to do this? 最好的方法是什么?
A way to achieve this is by using: 一种实现此目的的方法是使用:
def infinite_linspace():
den = 2
while True:
for i in range(1,den,2):
yield i/den
den <<= 1
Here we thus iterate with the numerator from 1 to den-1
(inclusive), and then double the denominator . 因此,这里我们用分子从1迭代到
den-1
(包括den-1
),然后将分母加倍。
The first 15 numbers are then: 然后,前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]
We can even put more intelligence into it to obtain the i -th element relatively fast as well: 我们甚至可以添加更多的智能以相对快速地获得第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
So now we can access in logarithmic time for instance the 10-th, 15-th and 123'456-th element: 因此,现在我们可以以对数时间访问第10个,第15个和第123'456个元素:
>>> l = Linspace()
>>> l[9]
0.3125
>>> l[14]
0.9375
>>> l[123455]
0.8837966918945312
Here is a shorter, pseudo O(1) way of directly computing the i-th element: 这是直接计算第i个元素的一种较短的伪O(1)方法:
def jumpy(i):
i = (i<<1) + 3
return i / (1<<i.bit_length()-1) - 1
list(map(jumpy, range(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]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.