You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

初始x值为负数时出现List IndexError的问题排查

问题原因分析
  1. 区间匹配逻辑错误:原代码用int(x)获取索引,而Python的int()对负数是向零取整,导致负数区间的x被错误分配到右侧区间(比如x=-1.5会被分到[-1,0]区间,而非正确的[-2,-1]区间)。当x接近Fx最后一个元素且不是整数时,Bi = index + 1会超出列表索引范围,触发IndexError。
  2. 错误的区间匹配同时导致近似结果失真:用错区间后,后续的插值计算基于错误的已知点,自然会出现结果偏差。
解决方案

1. 修复区间匹配逻辑

替换get_value中获取索引的方式,改为遍历Fx找到x所在的正确区间:

def get_value(self, x: float | int) -> float:
    # 处理x是已知点的情况
    if x in self.Fx:
        return self.Fy[self.Fx.index(x)]
    
    # 找到x所在的区间Ai,满足Fx[Ai] < x < Fx[Ai+1]
    Ai = None
    for i in range(len(self.Fx)-1):
        if self.Fx[i] < x < self.Fx[i+1]:
            Ai = i
            break
    if Ai is None:
        raise ValueError(f"x={x}超出已知点的范围[{self.Fx[0]}, {self.Fx[-1]}]")
    
    Bi = Ai + 1
    # 后续计算逻辑保持不变

2. 优化__call__方法的循环(可选,增强鲁棒性)

原循环逻辑在负数场景下可运行,但改为基于起始/结束点计算步数的方式更直观,避免因负数乘法产生的潜在误解:

def __call__(self, density: int):
    Ex, Ey = [], []
    start = self.Fx[0]
    end = self.Fx[-1]
    total_steps = int((end - start) * density)
    for step in range(total_steps + 1):
        x = start + step / density
        Ex.append(x)
        Ey.append(self.get_value(x))
    return (Ex, Ey)

完整修正后的代码

class Expand:
    def __init__(self, fx: list, fy: list, dfy: list):
        # 校验Fx是否严格递增,避免输入无序导致错误
        if not all(fx[i] < fx[i+1] for i in range(len(fx)-1)):
            raise ValueError("fx必须是严格递增的列表")
        self.Fx = fx
        self.Fy = fy
        self.dFy = dfy
    
    def get_value(self, x: float | int) -> float:
        # 处理x是已知点的情况
        if x in self.Fx:
            return self.Fy[self.Fx.index(x)]
        
        # 找到x所在的区间
        Ai = None
        for i in range(len(self.Fx)-1):
            if self.Fx[i] < x < self.Fx[i+1]:
                Ai = i
                break
        if Ai is None:
            raise ValueError(f"x={x}超出已知点的范围[{self.Fx[0]}, {self.Fx[-1]}]")
        
        Bi = Ai + 1
        Ax, Bx = self.Fx[Ai], self.Fx[Bi]
        Ay, By = self.Fy[Ai], self.Fy[Bi]
        dAy, dBy = self.dFy[Ai], self.dFy[Bi]

        if dAy == dBy:
            Vx = (Ax + Bx)/2
            Vy = (Ay + By)/2
        else:
            Vx = (By - Ay + dAy*Ax - dBy*Bx)/(dAy - dBy)
            Vy = Ay + dAy*(Vx - Ax)
        
        denominator = (Ax - Bx)**2
        p = (Ax - 2*Vx + Bx)/denominator
        if p != 0:
            q = 2*(Ax*Vx - 2*Ax*Bx + Vx*Bx)/denominator
            x = ((4*p*(x - Ax*Bx*p) + q*q)**0.5 - q)/(2*p)
        
        y = (Ay*((Bx - x)**2) + (Ax - x)*(Ax*By - 2*Vy*(Bx - x) - By*x))/((Ax - Bx)**2)

        return y

    def __call__(self, density: int):
        Ex, Ey = [], []
        start = self.Fx[0]
        end = self.Fx[-1]
        total_steps = int((end - start) * density)
        for step in range(total_steps + 1):
            x = start + step / density
            Ex.append(x)
            Ey.append(self.get_value(x))
        
        return (Ex, Ey)


if __name__ == "__main__":
    import matplotlib.pyplot as plt

    fx, fy, dfy = [-3, -2, -1, 0], [1, 1, 2, 6], [-0.577215664902, 0.422784335098, 1.8455686702, 7.53670601059]

    G = Expand(fx, fy, dfy)
    gx, gy = G(2)

    plt.plot(fx, fy, color="b", marker='o', label="已知点")
    plt.plot(gx, gy, color="r", linestyle='--', label="近似曲线")
    plt.legend()
    plt.show()

说明

  • 新增Fx严格递增的校验,避免因输入无序导致的逻辑错误。
  • 区间匹配改为遍历查找,无论正负区间都能正确定位x所在的相邻已知点。
  • 测试代码添加了图例和标记,便于观察近似效果。

内容的提问来源于stack exchange,提问作者M11X00

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 17:15:56