Python实现最小硬币数找零逻辑时出现无限循环问题求解
问题根源
你的代码有3个核心逻辑错误,和浮点精度、数据类型没有关系:
- 内层for循环的跳出逻辑错误
你在遍历硬币面额时,只要遇到当前面额大于剩余待凑金额,就直接break终止了整个for循环,根本不会继续遍历后面面额更小的硬币。比如整数分场景下找零77分,选完50、20之后剩余7分,接下来遍历到10分面额时7<10,你直接跳出循环,永远不会走到后面5、2、1分的面额,剩余的7分永远凑不齐,要么无限循环要么提前终止。 - 循环终止条件逻辑完全错误
tot_rest本身就是计算好的需要找零的总金额,你需要凑的目标值就是tot_rest,你写的payment != (tot_rest + resto_temp)属于逻辑混乱:tot_rest = payment - product_cost,代入后等式右边永远大于payment,条件永远成立,自然会触发无限循环。你后来改成payment > (tot_rest + resto_temp)更是完全偏离目标,凑到70分的时候tot_rest+resto_temp已经超过100,直接终止,结果自然不对。 - 面额匹配判断符号错误
你用tot_rest_temp > m判断是否可以选当前面额,当剩余待凑金额刚好等于某面额时(比如剩5分,当前面额是5),判断条件不成立,就不会选取该硬币,永远卡壳。
另外你代码里的continue是多余的,for循环执行完当前if块后会自动进入下一轮遍历,加不加不影响逻辑。
修正方案
你转成整数分计算的思路是完全正确的,可以彻底规避浮点精度问题。找零问题用贪心算法(从大到小选面额,能拿多少拿多少)对于你给出的面额体系可以保证硬币数量最少,根本不需要嵌套外层while循环,单层遍历就可以实现。
修正后的整数版代码(最稳妥,无精度问题):
# 面额从大到小排列,单位:分 coin = [50, 20, 10, 5, 2, 1] payment = 100 product_cost = 23 # 待找零总金额 tot_rest = payment - product_cost print(f"应找零: {tot_rest}分") rest_coin = [] remain = tot_rest # 剩余待凑金额 for m in coin: # 只要剩余金额大于等于当前面额,就拿完所有能拿的该面额硬币 while remain >= m: rest_coin.append(m) remain -= m # 剩余金额凑完直接结束遍历 if remain == 0: break print(f"最终找零硬币: {rest_coin}") print(f"硬币总数量: {len(rest_coin)}")
运行结果:
应找零: 77分 最终找零硬币: [50, 20, 5, 2] 硬币总数量: 4
如果要换回元为单位的小数计算,只需要把面额改回对应小数值、金额按比例缩放即可,但所有货币类计算都优先用整数最小单位存储,从根源上避免浮点精度误差。
内容的提问来源于stack exchange,提问作者Prectux
相关产品推荐
相关产品推荐

