⼈类做重复性的劳动没有效率,⽽计算机却能更快更准确的完成重复性劳动。所以以重复为特点的迭代法在编程中有着⼴泛的应⽤。实际项目中是否可以用不断更新变量值或者缩小搜索的区间范围的方法,来获得最终的解(或近似解、局部最优解)?如果是,那么你就可以尝试迭代法。
还记的那个有名的麦子故事吗?
古印度国王舍罕酷爱下棋,他打算重赏国际象棋的发明⼈宰相⻄萨·班·达依尔。这位聪明的⼤⾂指着象棋盘对国王说:“陛下,我不要别的赏赐,请您在这张棋盘的第⼀个⼩格内放⼊⼀粒⻨⼦,在第⼆个⼩格内放⼊两粒,第三⼩格内放⼊给四粒,以此类推,每⼀⼩格内都⽐前⼀⼩格加⼀倍的⻨⼦,直⾄放满64个格⼦,然后将棋盘上所有的⻨粒都赏给您的仆⼈我吧!”
国王⾃以为⼩事⼀桩,痛快地答应了。可是,当开始放⻨粒之后,国王发现,还没放到第⼆⼗格,⼀袋⻨⼦已经空了。随着,⼀袋⼜⼀袋的⻨⼦被放⼊棋盘的格⼦⾥,国王很快看出来,即便拿来全印度的粮⻝,也兑现不了对达依尔的诺⾔。
放满这64格到底需要多少粒麦子?这是个相当⼤的数字,在数学上是有对应⽅法的,就是
迭代法(Iterative Method)
迭代法,简单说就是:不断用旧的变量值,递推计算新的变量值。
回到刚才的故事:要求每⼀格的麦子都是前⼀格的两倍,那么前⼀格里麦子的数量就是旧的变量值,可以先记作 X n − 1 X_{n-1} Xn−1;⽽当前格子里麦子的数量就是新的变量值,我们记作 X n X_{n} Xn。这两
个变量的递推关系就是这样的:f ( X n X_{n} Xn) = f ( X n − 1 X_{n-1} Xn−1) X 2
迭代法的思想,很容易通过计算机语⾔中的循环语⾔来实现。计算机本身就适合做重复性的⼯作,我们可以通过循环语句,让计算机重复执⾏迭代中的递推步骤,然后推导出变量的最终值。
比如:
求数值的精确或者近似解: 典型的⽅法包括⼆分法(Bisection method)和⽜顿迭代法(Newton’s method)。
在⼀定范围内查找⽬标值: 典型的⽅法包括⼆分查找。
机器学习算法中的迭代: 相关的算法或者模型有很多,⽐如K-均值算法(K-means clustering)、PageRank的⻢尔科夫链(Markov chain)、梯度下降法(Gradient descent)等等。很多时候机器学习的过程,就是根据已知的数据和⼀定的假设,求⼀个局部最优解。⽽迭代法可以帮助学习算法逐步搜索,直⾄发现这种解。
国际象棋棋盘一共有64个格,则最后一格放麦子粒为:2^63=9223372036854775808 粒
# 初始化一个空列表来存储麦子数量
grains = []
# 循环直到达到64个格子
for i in range(64):
# 计算并添加当前格子应有的麦子数(每次翻倍)
grains.append(2**(i))
# 打印结果
for i, grain_count in enumerate(grains):
print(f"第{i+1}个小格有 {grain_count} 粒麦子")
# 结果将显示麦子数量随格子递增的情况