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

Python终端Plotter绘图类输出异常 缩放函数故障排查

终端函数绘图功能坐标缩放故障排查

我尝试实现终端函数绘图功能,但当前代码运行后无法输出正确的函数图形。初步判断问题出在scale_to_idx或scale_to_range坐标缩放函数中,但暂未找到修复方法。
该代码预期接收形如x**2的简单函数表达式,根据用户指定的x、y轴取值范围在终端绘制对应函数图像,完整代码如下:

class Plotter():
    def __init__(self, size, xrange, yrange):
        self.size = size
        self.xrange = xrange
        self.yrange = yrange
        self.refresh()

    def refresh(self):
        self.pixels = [["  " for i in range(self.size)] for i in range(self.size)]

        #Draw Left Boundary
        for y in range(self.size):
            self.pixels[y][0] = "*"

        #Draw Bottom Boundary
        for x in range(self.size):
            self.pixels[0][x] = '**'

    def display(self):

        for row in self.pixels:
            print("".join(row))

    def scale_to_idx(self, value, value_range): ##smth wrong with scale
        rel = (int(value) - int(value_range[0]))/(int(value_range[0]) - int(value_range[-1]))
        print("(int(value_range[0]) - int(value_range[-1]))", (int(value_range[0]) - int(value_range[-1])))
        print("int(value) - int(value_range[0]))", (int(value) - int(value_range[0])))
        idx = rel * self.size
        return idx

    def scale_to_range(self, idx, value_range): ##smth wrong with scale
        rel = idx / self.size
        value = int(value_range[0]) + rel * (int(value_range[-1]) - int(value_range[0]))
        return value


    def plot(self, f, plot_char): 
        for x_idx in range(self.size):
            x = self.scale_to_range(x_idx, self.xrange)
            y = f(x_idx)
            if y > int(self.yrange[0]) or y < int(self.yrange[1]):
                y_idx = int(self.scale_to_idx(x, self.yrange)) 
                self.pixels[y_idx][x_idx] = plot_char
            
def validate_range(value_range):
    if len(value_range) != 2:
        print("Enter two values separated by a space! Try again...")
        return False
    if value_range[0] >= value_range[1]:
        print("Lower end of range must be lower than higher end! Try again...")
        return False
    return True

if __name__ == "__main__":
    size = int(input("Enter plot size (Press [ENTER] for default) ") or 50)
    while True:
        xrange = input("Enter X-axis range seperated by space (default is '-10 10'): ") or "-10 10"
        yrange = input("Enter Y-axis range seperated by space (default is '-10 10'): ") or "-10 10"
        xrange = xrange.split()
        yrange = yrange.split()
        if validate_range(xrange) and validate_range(yrange):
            break
    plotter = Plotter(size, xrange, yrange)
                
    while True:
        answer = input("Do you wish to add (another) function? [y/n]: ")
        if answer == "y":
            func_string = input("Input function code with x as variable (e.g. 'x**2'): ")
            if not func_string:
                break
            plot_char = input("Set Plotting Character: ") or "--"            
            try:
                exec(f"def f(x): return {func_string}")
                plotter.plot(f, plot_char)          
            except SyntaxError:
                print("Invalid Function Expression! Try again...")
        elif answer == "n":
            break


    plotter.display()

已定位的代码错误点

  • scale_to_idx 函数跨度计算符号错误:分母误用value_range[0] - value_range[-1],导致计算出的相对位置为负值,索引完全错位,正确分母应为value_range[-1] - value_range[0]
  • plot 方法函数入参错误:计算y值时传入的是像素列索引x_idx,实际应该传入映射到x轴真实取值范围的x变量
  • plot 方法范围判断逻辑完全错误:原判断条件y > int(self.yrange[0]) or y < int(self.yrange[1])会放行所有超出y轴范围的点,且逻辑或无法筛选区间内值,正确判断应为y值落在[y轴最小值, y轴最大值]区间内才进行绘制
  • y轴坐标未做翻转:终端打印顺序是从上到下输出行,对应y轴坐标从最大值递减到最小值,原缩放逻辑直接映射会导致绘制出的函数上下颠倒
  • 坐标索引越界风险:原代码没有对计算出的y_idx做边界截断,当y值接近范围边缘时容易出现列表索引超出范围的报错
  • 坐标映射基准错误:原缩放逻辑以self.size为分母计算索引,有效索引范围为0到size-1,会导致最边缘点映射错位

修复后核心逻辑参考

将两个缩放函数和plot方法修改为如下逻辑即可正常绘图:

def scale_to_idx(self, value, value_range):
    v_min, v_max = int(value_range[0]), int(value_range[1])
    # 计算相对位置,截断到[0,1]区间避免越界
    rel = max(0, min(1, (value - v_min) / (v_max - v_min)))
    idx = int(rel * (self.size - 1))
    return idx

def scale_to_range(self, idx, value_range):
    v_min, v_max = int(value_range[0]), int(value_range[1])
    rel = idx / (self.size - 1)
    value = v_min + rel * (v_max - v_min)
    return value

def plot(self, f, plot_char): 
    y_min, y_max = int(self.yrange[0]), int(self.yrange[1])
    for x_idx in range(self.size):
        x = self.scale_to_range(x_idx, self.xrange)
        y = f(x)
        # 仅绘制y轴范围内的点
        if y_min <= y <= y_max:
            # y轴翻转,适配终端从上到下的打印顺序
            y_idx = self.size - 1 - self.scale_to_idx(y, self.yrange)
            self.pixels[y_idx][x_idx] = plot_char

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.02 03:18:25