NumPy将值环绕任意边界

2024-04-24 03:51:23 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个数组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
  1. 此函数没有正确获取包含/排除边界条件;对于wrap(x, -3),它返回array([ 3, 5, -3, -1, 1]),而5应该是-5。我不知道如何包含这个功能。你知道吗
  2. 而且显式的if子句看起来有些做作,我想知道是否可以用更一般的方式来处理它(小问题)。你知道吗

有人知道如何解决这个问题吗?你知道吗


Tags: 方法函数returnifdefnp数组array
2条回答

通过“包装”,我假设结果应该与x+ymod 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+ymod 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-ax中的所有值应在[a..b+(b-a)[范围内。你知道吗
  • x - (b-a)*(x >= b)(x >= b)(如果解释为整数)如果x >= b,则计算为1,否则计算为0。从x中减去b-a将从所有值>= b中减去b-a,并保持这些< b不变。你知道吗

假设您的输入数组已经在[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

相关问题 更多 >