步数模拟程序中计数器初始值相同但结果不同的逻辑疑问
问题
为何以下Python步数模拟程序中的计数器初始值相同,但分别计数不同内容后最终结果不同?
import random while True: fwd= random.randint(2,20) bkwd= random.randint(2,fwd-1) total=random.randint(10,85) f= 0 b = 0 t= 0 steps_taken= 0 if bkwd > fwd: break #I don't understand how below this part works while total > 0: f = 0 while fwd > f: if total > 0: print("F", end="") f=f+1 t=t+1 total=total-1 steps_taken= steps_taken+1 else: f = fwd t = t total = total steps_taken= steps_taken #Up until f=fwd b = 0 while bkwd > b: if total > 0: print("B", end="") t=t-1 b=b+1 total=total-1 steps_taken= steps_taken+1 else: b = bkwd t = t total = total steps_taken = steps_taken if f > total or b > total: break print(" ",t, "steps from the start") print("Forward:", f, "Backward:", b, "Total:", steps_taken )
程序需求说明:模拟一个人重复进行随机前进、后退的行走动作,前进步数范围为2-20,后退步数范围为2到前进步数减1(始终小于前进步数),总步数随机为10-85。程序需输出行走轨迹,以及最终与起点的距离。示例如下:
- 若前进步数为4、后退步数为2、总步数为13,程序应输出:
FFFFBBFFFFBBF = 5 Steps from the start
- 若前进步数为5、后退步数为3、总步数为16,程序应输出:
FFFFFBBBFFFFFBBB = 4 Steps from the start
问题解析
四个初始值为0的计数器最终结果不同,核心原因是它们的计数逻辑完全独立,各自承担的角色不一样:
f:单次前进阶段的步数计数器
每次进入前进循环时都会被重置为0,它只统计当前一轮前进动作中走了多少步。比如前进步数设为4,它会从0涨到4,完成一轮前进后,下一轮前进又会被重置回0重新计数。最终它的值是最后一轮前进实际走的步数(如果总步数不够走完一轮前进,就是剩余的步数)。b:单次后退阶段的步数计数器
和f逻辑一致,每次进入后退循环时重置为0,只统计当前一轮后退动作中走了多少步。比如后退步数设为2,它会从0涨到2,下一轮后退又重置回0。最终值是最后一轮后退实际走的步数。t:当前与起点的距离
这是累计的位置偏移量:每走一步前进就+1,每走一步后退就-1,全程不会被重置。比如前进4步后t变成4,后退2步后t变成2,再前进4步t变成6,完全是跟踪当前位置的累计值。steps_taken:总共走的步数
它统计所有前进+后退的总步数,每走一步(不管F还是B)就+1,全程累计不重置,最终值等于初始设定的total(因为直到total减到0才停止)。
额外:原程序的小问题
原程序最后一行输出的Forward:和Backward:显示的是最后一轮的步数,不是总前进/后退步数,和示例输出逻辑不符。如果要输出总前进/总后退步数,需要额外加两个累计计数器,修正后的核心代码如下:
import random while True: fwd= random.randint(2,20) bkwd= random.randint(2,fwd-1) total=random.randint(10,85) t= 0 steps_taken= 0 total_f = 0 # 总前进步数 total_b = 0 # 总后退步数 if bkwd > fwd: break while total > 0: f = 0 while fwd > f and total > 0: print("F", end="") f +=1 total_f +=1 t +=1 total -=1 steps_taken +=1 b = 0 while bkwd > b and total > 0: print("B", end="") b +=1 total_b +=1 t -=1 total -=1 steps_taken +=1 print(f" = {t} Steps from the start") print(f"Forward: {total_f}, Backward: {total_b}, Total: {steps_taken}") break # 原循环会无限生成随机参数,这里加break只运行一次
这样输出就会匹配示例逻辑,比如前进步数4、后退2、总步数13的情况,总前进9步、总后退4步,最终位置9-4=5,和示例一致。
内容的提问来源于stack exchange,提问作者koko

