You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python金额面值计算循环处理小数时0.01面值计数错误问题

问题:Python处理小数金额找零计算时的精度错误

我正在学习Python,需要根据输入金额1575.78计算1000、500、200、100、50、20、10、5、1、0.25、0.01这些面值的数量。但编写的代码处理该小数金额时出现错误,整数金额(比如1500、20)计算结果正确。

错误代码

def withdraw_money():
    denoms = (1000, 500, 200, 100, 50, 20, 10,5,1,.25,0.01)
    while True:
        try:
            withdraw = 1575.770
            break
        except Exception as e:
            print('Incorrect input: %s' % e)
    

print("Here is the bill breakdown for the amount input")
for d in denoms:
    count = withdraw // d
    print('P%i = %i' % (d, count))
    withdraw -= count * d
 

withdraw_money()

当前错误输出

Here is the bill breakdown for the amount input

P1000 = 1
P500 = 1
P200 = 0
P100 = 0
P50 = 1
P20 = 1
P10 = 0
P5 = 1
P1 = 0
P0.25 = 3
P0.01 = 2

其中P0.01 = 2应为P0.01 =3

问题原因

这是浮点数的精度缺陷导致的。计算机以二进制存储浮点数,0.01这类十进制小数无法被二进制精确表示,计算过程中会产生微小误差。比如1575.78经过前面的面值扣除后,剩余金额可能是一个略小于0.03的数(如0.029999999999994316),用这个数除以0.01时,//取整得到的就是2而非3。

解决方法

处理金额计算时,优先用整数运算或高精度十进制运算避免浮点数误差,以下两种方案都可行:

方案1:转换为整数(以分为单位)

把所有金额转换为分(整数),彻底规避浮点数问题:

def withdraw_money():
    # 面值转换为分(整数)
    denoms = (100000, 50000, 20000, 10000, 5000, 2000, 1000, 500, 100, 25, 1)
    while True:
        try:
            # 输入金额转成分,取整避免精度误差
            withdraw = int(round(1575.78 * 100))
            break
        except Exception as e:
            print('Incorrect input: %s' % e)
    
    print("Here is the bill breakdown for the amount input")
    for d in denoms:
        count = withdraw // d
        # 输出时转回原面值
        print('P%.2f = %i' % (d / 100, count))
        withdraw -= count * d

withdraw_money()

正确输出:

Here is the bill breakdown for the amount input
P1000.00 = 1
P500.00 = 1
P200.00 = 0
P100.00 = 0
P50.00 = 1
P20.00 = 1
P10.00 = 0
P5.00 = 1
P1.00 = 0
P0.25 = 3
P0.01 = 3

方案2:使用decimal模块处理高精度十进制

用Python内置的decimal模块直接处理十进制数,保留精确的小数运算:

from decimal import Decimal, getcontext

def withdraw_money():
    # 设置足够的计算精度
    getcontext().prec = 20
    denoms = (Decimal('1000'), Decimal('500'), Decimal('200'), Decimal('100'), 
              Decimal('50'), Decimal('20'), Decimal('10'), Decimal('5'), 
              Decimal('1'), Decimal('0.25'), Decimal('0.01'))
    while True:
        try:
            withdraw = Decimal('1575.78')
            break
        except Exception as e:
            print('Incorrect input: %s' % e)
    
    print("Here is the bill breakdown for the amount input")
    for d in denoms:
        count = withdraw // d
        print('P%s = %i' % (d, count))
        withdraw -= count * d

withdraw_money()

该方案无需手动转换单位,适合对精度要求高的场景,同样能得到正确的找零结果。

内容的提问来源于stack exchange,提问作者MiksMeister

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 07:35:20