排除区间的端点
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)
我有一个二维网格,其间隔为 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)