Python循环中v0被意外更新致norm_为0的问题求助
问题根源:Python中数组的浅拷贝导致的意外更新
你遇到的问题本质是Python中numpy数组的赋值是浅拷贝(引用传递),而MATLAB中默认是深拷贝(值传递)——这直接导致v0和v指向同一块内存区域,当你修改v的元素时,v0也会跟着变化,最后计算v - v0自然全是0,norm_就变成0了。
具体分析你的代码:
v = array([0, 0]) # 假设这是numpy数组 norm_ = 1 n = 0 while norm_ > tol: v0 = v # 这里只是让v0指向v的内存地址,不是创建新副本! v[0] = max(5.0 + 0.5 * lmbda * v[0] + 0.5 * lmbda * v[1], 10.0 + lmbda * v[1]) v[1] = -1 + lmbda * v[1] norm_ = norm(v - v0, inf) # 此时v和v0已经是同一个数组,相减为0 n += 1
当执行v0 = v时,并没有复制v的内容,只是让v0成为v的引用。所以后续修改v[0]和v[1]的时候,v0的元素也会被同步修改——因为它们根本就是同一个数组。最后计算v - v0得到的是全0数组,无穷范数自然是0,循环直接退出。
而MATLAB中,v0 = v会默认创建一个新的数组副本,修改v不会影响v0,所以逻辑能正常运行。
解决方案:创建数组的深拷贝
要解决这个问题,你需要显式地创建v的副本赋值给v0,而不是直接引用。在numpy里有几种常用方法:
- 使用
copy()方法:v0 = v.copy() - 重新构造数组:
v0 = np.array(v) - 使用切片(对一维数组有效):
v0 = v[:]
修改后的代码示例:
import numpy as np # 确保导入numpy库 v = np.array([0, 0]) norm_ = 1 n = 0 tol = 1e-6 # 假设这是你定义的收敛阈值 lmbda = 0.5 # 假设这是你使用的参数值 while norm_ > tol: v0 = v.copy() # 显式创建数组副本,保存当前v的状态 v[0] = max(5.0 + 0.5 * lmbda * v[0] + 0.5 * lmbda * v[1], 10.0 + lmbda * v[1]) v[1] = -1 + lmbda * v[1] norm_ = np.linalg.norm(v - v0, np.inf) # 计算两次迭代的无穷范数差值 n += 1
这样v0会保存每次循环开始时v的状态,修改v不会影响v0,计算出来的norm_就是两次迭代之间的真实差值,循环就能按预期执行了。
内容的提问来源于stack exchange,提问作者Vaolter
相关产品推荐
相关产品推荐

