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

Python重力场计算函数异常:仅屏幕底部行有非零值求助

问题:重力场计算函数仅屏幕底部行有值,其余全为0

我是大学编程新手,学编程才几个月,正在做一个基于Pygame的重力场强度可视化程序。基于已验证可用的引力计算器修改了重力场计算函数,用来计算屏幕每个像素点的重力场,但返回的numpy数组里除了屏幕底部行,其他元素全是0,找不到原因。

测试场景:用100x100的屏幕,在(50,50)位置放一个质量为6000000000000的单个质量体,问题依然存在。

当前代码

# 计算屏幕上每个点由所有质量体产生的引力场的函数,质量和位置由列表定义,同时传入屏幕尺寸
def gravfield(mass, x, y, screen_width, screen_height):

    # 定义屏幕位置点
    x_screen = list(range(screen_width))
    y_screen = list(range(screen_height))

    # 定义存储屏幕每个像素点场强的数组
    field = np.zeros((screen_width, screen_height))   
        
    # 用向量法计算每个质量体产生的引力场    
    for i in range(len(x_screen)):
        for n in range(len(y_screen)):

            # 存储每个质量体产生的场强分量的列表
            x_fields = []
            y_fields = []
            
            for j in range(len(mass)):

                # 计算从质量体到目标点的位置向量
                x_distance = x[j] - x_screen[i]
                y_distance = y[j] - y_screen[n]

                # 计算质量体和目标点的距离,同时给质量体所在像素赋唯一值以避免除零错误
                distance = np.sqrt((x_distance**2) + (y_distance**2))
                if distance == 0:
                    x_fields = 0
                    y_fields = 0
                    
                else:
                     
                        # 计算质量体到目标点的单位向量
                        x_unit_vector = x_distance / distance
                        y_unit_vector = y_distance / distance

                        # 计算场强大小
                        magnitude = (G * mass[j] * 1) / (distance ** 2)

                        # 计算各方向的场强分量,并添加到存储所有质量体分量的列表中
                        x_field = (magnitude * x_unit_vector) 
                        y_field = (magnitude * y_unit_vector) 
                        x_fields.append(x_field)
                        y_fields.append(y_field)

                
        # 求和所有方向的场强分量得到合场强,再计算其大小并赋值给对应屏幕像素的数组位置
           
        gx = sum(x_fields)
        gy = sum(y_fields)
        g = np.sqrt((gx**2) + (gy**2))
        field[n, i] = g

    return field
问题原因与修复方案

核心问题:缩进错误

你把计算合场强并赋值给field的代码块(gx = sum(...)到field[n,i] = g)放在了外层i循环的末尾,而不是内层n循环的末尾。这意味着:

  • 外层i循环(遍历x方向)执行时,内层n循环(遍历y方向)会完整跑一遍,但只有当n循环结束后(此时n的值固定为screen_height-1,也就是屏幕最后一行的索引),才会执行一次赋值操作。
  • 所以整个field数组里,只有n=screen_height-1对应的那一行(屏幕底部行)会被赋值,其他行都保持初始的0值。

修复后的代码

# 计算屏幕上每个点由所有质量体产生的引力场的函数,质量和位置由列表定义,同时传入屏幕尺寸
def gravfield(mass, x, y, screen_width, screen_height):

    # 定义屏幕位置点
    x_screen = list(range(screen_width))
    y_screen = list(range(screen_height))

    # 定义存储屏幕每个像素点场强的数组
    field = np.zeros((screen_width, screen_height))   
        
    # 用向量法计算每个质量体产生的引力场    
    for i in range(len(x_screen)):
        for n in range(len(y_screen)):

            # 存储每个质量体产生的场强分量的列表
            x_fields = []
            y_fields = []
            
            for j in range(len(mass)):

                # 计算从质量体到目标点的位置向量
                x_distance = x[j] - x_screen[i]
                y_distance = y[j] - y_screen[n]

                # 计算质量体和目标点的距离,同时给质量体所在像素赋唯一值以避免除零错误
                distance = np.sqrt((x_distance**2) + (y_distance**2))
                if distance == 0:
                    x_fields = [0]  # 改为列表,避免sum时报错
                    y_fields = [0]
                    
                else:
                     
                        # 计算质量体到目标点的单位向量
                        x_unit_vector = x_distance / distance
                        y_unit_vector = y_distance / distance

                        # 计算场强大小
                        magnitude = (G * mass[j] * 1) / (distance ** 2)

                        # 计算各方向的场强分量,并添加到存储所有质量体分量的列表中
                        x_field = (magnitude * x_unit_vector) 
                        y_field = (magnitude * y_unit_vector) 
                        x_fields.append(x_field)
                        y_fields.append(y_field)

            # 注意这里的缩进:放到n循环内部,每个像素点都执行一次
            # 求和所有方向的场强分量得到合场强,再计算其大小并赋值给对应屏幕像素的数组位置
            gx = sum(x_fields)
            gy = sum(y_fields)
            g = np.sqrt((gx**2) + (gy**2))
            field[n, i] = g

    return field

额外优化说明

  • 当distance == 0时,原代码把x_fields和y_fields赋值为整数0,后续sum(x_fields)会报错(因为不能对整数用sum),所以改为赋值为[0]这样的列表,保证sum操作正常执行。
  • 若后续屏幕尺寸增大,嵌套循环的计算效率会很低,可以尝试用numpy的向量化操作替代循环,不过先把逻辑跑通再优化性能更适合新手阶段。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 15:05:04