排除间隔的端点

问题描述

我有一个二维网格,其间隔为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)。我使用以下功能

用于2D

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,endpoint=False)
y = np.linspace(LeftY,RightY,Ny,endpoint=False)
xv,yv = np.meshgrid(x,y)