将C语言实现的COVID-19最小二乘法拟合代码迁移至Python时遭遇IndexError问题求助
解决迁移代码中的两个IndexError问题
我来帮你一步步分析并解决这两个索引越界的错误:
第一个错误:a[i] = (a[i-1] + g1[i]) 索引越界
这个错误主要由三个问题导致:
- g1数组初始化逻辑错误:你先创建了长度为
len(dados)的全0数组,又append了len(dados)个1,导致g1长度变为2*len(dados),和原C语言中gbarra1全1的逻辑不符。 - 循环条件不合理:原C语言数组是固定224长度,你的Python代码中
cont的循环条件是cont < len(dados),当cont接近数组末尾时,cont+28会远超过数组最大索引,直接引发越界。 - 初始累加值处理不当:当
cont=0且i=0时,a[i-1]会取a[-1](Python中是数组最后一个元素),但原C语言中这属于未定义行为,逻辑上应该从0开始累加。
修复方案:
- 修正g1的初始化:
# 直接创建和dados等长的全1数组,和原C的gbarra1逻辑一致 g1 = [1.0] * len(dados) - 调整cont的循环条件,确保窗口不超出数组范围:
length = 28 # 保证cont + length 不超过数组长度,避免i越界 while cont <= len(dados) - length: - 处理累加的初始值问题,避免访问
i-1越界:while i < (cont + length): # 当i是窗口第一个元素时,前一个值用0(初始累加起点) prev_a = a[i-1] if i > 0 else 0.0 a[i] = prev_a + g1[i] prev_b = b[i-1] if i > 0 else 0.0 b[i] = prev_b + a[i] prev_d = d[i-1] if i > 0 else 0.0 d[i] = prev_d + a[i] * a[i] prev_f = f[i-1] if i > 0 else 0.0 f[i] = prev_f + dados[i] prev_g = g_arr[i-1] if i > 0 else 0.0 g_arr[i] = prev_g + dados[i] * t[i] # 后续的x,y,final等计算保持不变 denominator = b[i] * b[i] - a[i] * d[i] x[i] = ((-d[i] * f[i] + b[i] * g_arr[i]) / denominator) if denominator != 0 else 0.0 y[i] = ((b[i] * f[i] - a[i] * g_arr[i]) / denominator) if denominator != 0 else 0.0 final[i] = (x[i] + y[i] * t[i]) r0[i] = (np.exp(y[i] * 5.4)) p_a[i] = (np.exp(x[i])) i += 1
第二个错误:er2[i] = er2[i+1] + ... 索引越界
这个错误是因为当i是数组最后一个索引时,i+1超出了列表的索引范围(列表索引从0到len(dados)-1)。原C语言中这里其实存在隐患(访问数组越界的未定义行为),迁移到Python后会直接报错。
修复方案:
调整er2的计算顺序,从窗口的末尾往前遍历,这样i+1只会在窗口内部或数组末尾时用0作为初始值:
# 先完成当前窗口内所有final、r0等计算后,再计算er2和er while i < (cont + length): # ... 前面的a,b,d,f,g_arr,x,y,final,r0,p_a计算 i += 1 # 从窗口最后一个元素往前计算误差 for i in range(cont + length - 1, cont - 1, -1): # 当i是数组最后一个元素时,i+1越界,用0作为初始值 next_er2 = er2[i+1] if i < len(dados) - 1 else 0.0 er2[i] = next_er2 + ((dados[i] - final[i]) ** 2) er[i] = np.sqrt(er2[i]) / length
完整修改后的核心代码片段
import numpy as np # 假设dados和t已经定义好 g1 = [1.0] * len(dados) a = [0.0]*(len(dados)) b = [0.0]*(len(dados)) f = [0.0]*(len(dados)) d = [0.0]*(len(dados)) g_arr = [0.0]*(len(dados)) # 避免和numpy的g函数冲突,重命名为g_arr x = [0.0]*(len(dados)) y = [0.0]*(len(dados)) r0 = [0.0]*(len(dados)) final = [0.0]*(len(dados)) er = [0.0]*(len(dados)) er2 = [0.0]*(len(dados)) p_a = [0.0]*(len(dados)) length = 28 cont = 0 while cont <= len(dados) - length: i = cont while i < (cont + length): prev_a = a[i-1] if i > 0 else 0.0 a[i] = prev_a + g1[i] prev_b = b[i-1] if i > 0 else 0.0 b[i] = prev_b + a[i] prev_d = d[i-1] if i > 0 else 0.0 d[i] = prev_d + a[i] * a[i] prev_f = f[i-1] if i > 0 else 0.0 f[i] = prev_f + dados[i] prev_g = g_arr[i-1] if i > 0 else 0.0 g_arr[i] = prev_g + dados[i] * t[i] denominator = b[i] * b[i] - a[i] * d[i] # 避免除零错误 if denominator == 0: x[i] = 0.0 y[i] = 0.0 else: x[i] = (-d[i] * f[i] + b[i] * g_arr[i]) / denominator y[i] = (b[i] * f[i] - a[i] * g_arr[i]) / denominator final[i] = x[i] + y[i] * t[i] r0[i] = np.exp(y[i] * 5.4) p_a[i] = np.exp(x[i]) i += 1 # 从后往前计算误差 for i in range(cont + length - 1, cont - 1, -1): next_er2 = er2[i+1] if i < len(dados) - 1 else 0.0 er2[i] = next_er2 + ((dados[i] - final[i]) ** 2) er[i] = np.sqrt(er2[i]) / length writer.writerow([dados[cont], final[cont], x[cont], p_a[cont], y[cont], er[cont]]) cont += 1
额外提示:我还把变量g重命名为g_arr,避免和numpy的g函数冲突,同时添加了分母为零的判断,防止出现除零错误。
内容的提问来源于stack exchange,提问作者Crimeiaman
相关产品推荐
相关产品推荐

