问 题
是这样的,我没有找到Python里面的list数乘与加减运算,于是自己定义了它们,代码如下:
def ntl(n1: float, list1: list) -> list:
for i in range(0, len(list1)):
list1[i] *= n1
return list1
def lsb(list1: list, list2: list) -> list or bool:
if len(list1) != len(list2):
return False
for i in range(0, len(list1)):
list1[i] -= list2[i]
return list1
前面的ntl是向量数乘(n times list),后面的lsb是向量相减(list subtraction)。这两个函数在后面被调用,调用的地方是一个解方程算法:即解决au+bv=gcd(u,v)这样的线性丢番图方程,或者数论里面提到的裴蜀(Bézout)定理,其中u,v是两个正整数,gcd是最大公约数。
代码如下:
def bezout(n1: int, n2: int) -> int or bool:
if type(n1) != int or type(n2) != int:
return False
list1 = [1, 0, n1]
list2 = [0, 1, n2]
while list1[2] != 0:
list3 = list1 # 01
list1 = lsb(list2, ntl(int(list2[2] / list1[2]), list1)) # 02
list2 = list3 # 03
return list2
我使用Pycharm社区版运行这些代码。在调试时,我选择了bezout(9785, 18967)进行验算。然而在断点# 02处,每当运行到第3轮循环时,list3的值都会自发改变,见下面的截图:
代码中没有全局变量,我认为不同函数中的局部变量不会相互影响,况且在之前的代码中,list3没有出现过。这个算法本身是没有问题的。bezout这个函数输出的结果在算数上是成立的,最终输出:
6257064 x 9785 - 3227994 x 18967 == 9042 然而化简后的结果应该是:692 x 9785 - 357 x 18+67 == 1
我不知道到底发生了什么,请各位帮忙看看,多谢!
解决方案
代码
list1 = lsb(list2, ntl(int(list2[2] / list1[2]), list1))
这里的 list1 是一个列表, 一个可变对象, 又因为在函数 lsb 中, 对于list1的修改, 是直接修改当中的元素, 又因为它是可变对象, 所以实际上, 你修改的是全局的 list1, 而不是你想象中的 局部变量list1
如果真的想要实现你想要的那种, 局部变量list1, 那就用深拷贝的方式吧
import copy
list1 = lsb(list2, ntl(int(list2[2] / list1[2]), copy.deepcopy(list1)))
PS:
文中代码:
if type(n1) != int or type(n2) != int:
return False
在判断对象类型时, 不应该用这种方式, 而是用isinstance函数:
if not isinstance(n1, int) or not isinstance(n2, int):
return False
扫一扫关注IT屋
微信公众号搜索 “ IT屋 ” ,选择关注与百万开发者在一起