排除区间的端点

Exclude the endpoints of an interval

我有一个二维网格,其间隔为 Xleft = -1.5 Xright = 1.5,Ydown = -1.5 Yup = 1.5。 Nx 和 Ny 是指示我想要多少间隔的变量。问题起源于一维,所以我们转到一维来简化。

我的区间是[-1.5,1.5],我们取N=12。我的网格步长为 3/12 = 0.25。我想输出一个包含内部点的数组:(-1.5, 1.5)。我使用以下功能。

对于二维

np.mgrid[intervalX,intervalY]

一维

np.mgrid[intervalX] = np.mgrid[start:stop:stepsize]

因为开始将是字面上的开始,而停止将是停止 - dx。我将内部点数组定义为:

LeftX  = -1.5
RightX =  1.5

Nx = 12 

x_int = RightX - LeftX #interval in the x-direction

dx = (RightX - LeftX)  / Nx #grid step in x-direction

matrix0 = np.mgrid[LeftX+dx:RightX:(x_int/Nx)]

预期的输出是:

[-1.25 -1.   -0.75 -0.5  -0.25  0.    0.25  0.5   0.75  1.    1.25]

大部分时间都是正确的。

但在某些情况下,对于特定的 N,程序会执行一些意想不到的事情:

N=9 的输出:

[-1.16666667 -0.83333333 -0.5        -0.16666667  0.16666667  0.5
  0.83333333  1.16666667  1.5]

你看到右边界点包含在数组中。我期望相同的数组期望最正确的 1.5。但这是不希望的。 N=10 或 N=22 时也会发生同样的情况。

这基本上是一个数值舍入误差。 Some more information.

mgrid[start:end:step](或arange)里面发生的事情可以简化成这样:

def mgrid(start, end, step)
    a = [start]
    i = 1
    while start+i*step < end:
        a.append(start+i*step)
        i += 1
    return a

以您的号码为例并说明失败的地方:

LeftX = -1.5
RightX = 1.5
Nx = 9
dx = (RightX - LeftX) / Nx

#    start        + i * step
a8 = (LeftX + dx) + 8 * dx 
# 1.4999999999999998
a8 < RightX
# True

所以 a8 在数值上比你的端点 1.5 略小,因此被添加到间隔中。然而它显示为 1.5 因为它非常接近。

作为解决方案,您可以使用 np.linspace() 函数。 结果默认包括起点和终点,您可以只使用元素 x[1:-1],或者移动起点和终点:

import numpy as np
x1 = np.linspace(LeftX, RigthX, Nx+1)x[1, :-1]
x2 = np.linspace(LeftX+dx, RightX-dx, Nx-1)

通过显式包含端点,您不必担心 由于舍入错误,检查 start + i*step < end 给出了最后一个 index 的错误结果。

或者你可以使用一个小的 epsilon,你知道它肯定小于你的步长,然后做这样的事情:

eps = 1e-10
np.mgrid[LeftX+dx:RightX-eps:dx]

通过减去这个 epsilon,您可以确保检查 start + i*step < end 总是给出预期的结果。

对于非整数步骤请使用 numpy linspace 因为它可以更好地处理端点

np.linspace(LeftX, RightX, Nx, endpoint=False)

然后对于 2D 你可以使用 numpy meshgrid

x= np.linspace(LeftX, RightX, Nx, endpoint=False)
y = np.linspace(LeftY, RightY, Ny, endpoint=False)
xv, yv = np.meshgrid(x, y)