我有一个数组x
,其值包含在[a, b]
(包括a
,包括b
中)内。现在,我想计算x + y
(对于随机y
),以使x + y
仍包含在[a, b]
中,方法是将结果值环绕在左边界或右边界(无论哪个交叉) )。
因为一个例子值得一千个单词:
>>> a, b = -5, 5
>>> x = np.array([-4, -2, 0, 2, 4])
>>> wrap(x, 3) # Compute x + 3.
[-1, 1, 3, -5, -3]
>>> wrap(x, -3) # Compute x - 3.
[3, -5, -3, -1, 1]
我想出了以下实现,但并不完全令人满意。
def wrap(x, y):
if y > 0:
return (x - a + y) % (b - a) + a
elif y < 0:
return (x - b + y) % (a - b) + b
else:
return x
wrap(x, -3)
,它返回array([ 3, 5, -3, -1, 1])
,而5
应该是-5
。我不确定如何包含此功能。if
子句看起来有些虚假,我想知道是否可以更一般的方式处理(次要问题)。有人知道如何解决这个问题吗?
答案 0 :(得分:1)
通过“包装”,我认为结果应与x+y
mod b-a
一致。 (请注意,b-a
是这种情况下的“窗口大小”)
请考虑特殊情况a==0
。我们有:
def wrap(x, y):
return (x + y) % b
直截了当,对吧?请注意,Python中的%
是按底模的-结果的符号始终与除数的符号相同。因此结果将位于[0..b[
中。
在更一般的情况下:
def wrap(x, y):
return (x + y - a) % (b-a) + a
直接证明返回值与x+y
mod b-a
是一致的。
还请注意,这是OP代码中的第一种情况。对于y
的所有值均有效。
但是,如果x
是一个numpy数组,它将执行len(x)
%
操作,这可能会很慢。因此,可以执行以下操作:
def wrap2(x, y):
y %= b - a
x = x + y
return x - (b-a)*(x >= b)
应该更快。 Try it online!
说明:
y %= b-a
:将y
减小到[0..b-a[
范围。这不会影响结果。x = x + y
:将y
添加到x
。在此步骤之后,x
将包含正确的值,以b-a
为模。 x
中的所有值都应在[a..b+(b-a)[
范围内。x - (b-a)*(x >= b)
:如果(x >= b)
,1
(如果解释为整数)则为x >= b
,否则为0
。从b-a
中减去x
乘以b-a
的所有值,然后减去>= b
,并使这些< b
保持不变。答案 1 :(得分:0)
假设您的输入数组已经在[a,b)范围内,那么我们可以将wrap
重写为以下函数;
def wrap(x,y,a,b):
if y > 0:
x += y
x[x >=b] -= (b-a)
elif y < 0:
x += y
x[x < a] += (b-a)
return x