处理金钱的时候,对于浮点的舍入误差你们是怎么处理的呢? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
dangyuluo

处理金钱的时候,对于浮点的舍入误差你们是怎么处理的呢?

  •  
  •   dangyuluo 2020 年 1 月 12 日 6670 次点击
    这是一个创建于 2296 天前的主题,其中的信息可能已经有所发展或是发生改变。

    前情提要:

    浮点运算结果不准确算不算是 bug ?任何人都不想得到不准确的结果吧 https://v2ex.com/t/637166#reply54


    假设有 10 块钱需要给三个人平均分配,精确到分。如果纯粹是四舍五入的话,每个人都会得到 3.33 元。这时候剩下的 1 分钱应该怎么处理呢?

    我不是做这行的,单纯只是好奇。

    39 条回复    2020-01-13 16:10:04 +08:00
    Xbluer
        1
    Xbluer  
       2020 年 1 月 12 日   2
    最后一个人得款是总额减去其他人得款。
    eason1874
        2
    eason1874  
       2020 年 1 月 12 日
    不会处理的可以把那 0.01 转给我,把余数都给我,就没有余数了。
    azh7138m
        3
    azh7138m  
       2020 年 1 月 12 日 via Android
    不是 bug,因为它是浮点数。
    怎么处理看 PM 心情了。
    ipwx
        4
    ipwx  
       2020 年 1 月 12 日 via Android
    用 decimal 不用 float,流行的语言基本标准库都有。
    loading
        5
    loading  
       2020 年 1 月 12 日
    金融计算有专门的库,不会有误差。

    记得有个方案是,把金额按 1000 倍存的。你的 3.33 元,在数据库是 3330
    dangyuluo
        6
    dangyuluo  
    OP
       2020 年 1 月 12 日
    @ipwx decimal 并不解决求和的问题啊。
    loading
        7
    loading  
       2020 年 1 月 12 日
    对于你这个分钱问题,似乎是有处理方式的,记不起来了。
    ipwx
        8
    ipwx  
       2020 年 1 月 12 日 via Android
    @dangyuluo 那就用 fraction,Python 标准库就有。
    andy101wong
        9
    andy101wong  
       2020 年 1 月 12 日 via Android   2
    现实怎么处理就怎么处理, 计算机解决不了 3.3333..... ,现实也做不到 10 元钱三等分啊。
    delectate
        10
    delectate  
       2020 年 1 月 12 日
    小数点后取两位数,不进行任何四舍五入。
    总金额再减去每份求和,得到差额,加入其中某一份即可。

    这也是大多数电商、支付平台分期的算法。
    dangyuluo
        11
    dangyuluo  
    OP
       2020 年 1 月 12 日
    @andy101wong 哈哈哈,我光想着技术怎么处理了,忽略了现实的问题
    Mavious
        12
    Mavious  
       2020 年 1 月 12 日
    某金融平台,很直接,不搞四舍五入,直接砍小数。
    比如应分配 13.33333 元,只给你 13.33 ,应得 16.598 元,只给你 15.59 ,小数点后第三位直接砍掉,不进位。
    至于多出的那一分钱,嗯哼,当然是平台拿走啦,轮不到用户的。
    ershierdu
        13
    ershierdu  
       2020 年 1 月 12 日 via iPhone
    看标题我还以为是说用 float 存金额…
    hhyyd
        14
    hhyyd  
       2020 年 1 月 12 日
    我们现在做的是,个人分 10 块,3.33 ,3.33 ,10-3.33-3.33 ,减法是没有误差的。也不会因为 0.01 而影响用户体验
    tfdetang
        15
    tfdetang  
       2020 年 1 月 12 日
    怎么根据我所知,金融行业通行的标准做法是 四舍六入五成双。
    imn1
        16
    imn1  
       2020 年 1 月 12 日
    不用电脑你说 10 块钱 3 个人怎么平分?

    电脑只是工具……不如上街问问那些“智能机器人”这个问题,看看是什么答案,会不会不同机器人有不同的答案
    fkmc
        17
    fkmc  
       2020 年 1 月 12 日
    入库六位,百分比计算,加到最后
    ziseyinzi
        18
    ziseyinzi  
       2020 年 1 月 12 日 via Android   6
    某次淘宝买一个一元包邮的东西,发现可以花呗免息分期。变成了 0.33 元 x3 期,省了一分
    des
        19
    des  
       2020 年 1 月 12 日
    发现这个问题,然后去补了一下知识,下面是我总结的,不一定完全对
    1、不能用浮点存小数是以讹传讹
    2、不同场景有不同处理,平分一般是加到最后一个人
    3、银行还是四舍五入用的最多,主要还是接受的人最多
    4、银行会定期对账,这些舍入应该都是在可接受的范围内的
    5、银行也在大把的用浮点数。最重要的一点是,误差可控,就比如计算复利
    6、钱其实精度要求还算是低的,麻烦的有很多,比如金价
    7、误差其实只在进制转换时发生(这个我也不是很确定)

    如果有哪里说的不对,希望有人能帮忙指正一下
    n121
        20
    n121  
       2020 年 1 月 13 日
    @ziseyinzi 照理说这种情况最后一期应该扣 0.34 才对呀
    czhfrank
        21
    czhfrank  
       2020 年 1 月 13 日 via iPhone
    除法出问题是你分钱的时候的问题,不是记账的问题,记账只记加减,从一个人口袋到另一个人口袋。这问题跟计算机更是八竿子打不着
    NewTab12138
        22
    NewTab12138  
       2020 年 1 月 13 日
    为什么不以分为单位来算,而使用元为单位
    KyonLi
        23
    KyonLi  
       2020 年 1 月 13 日
    @NewTab12138 一千分平均分给三人不还是一样的问题
    hc181533609
        24
    hc181533609  
       2020 年 1 月 13 日
    @KyonLi 看最小的单位呗 分还是厘
    hc181533609
        25
    hc181533609  
       2020 年 1 月 13 日
    @KyonLi 不好意思 回错人了
    fancy111
        26
    fancy111  
       2020 年 1 月 13 日
    程序设计的时候就没设计所谓平分的状态,10 元给三人的时候肯定设计的是有一个多一点余数的。
    而且本身 10 元就不可能平分给三个人吧。
    ccgoing10
        27
    ccgoing10  
       2020 年 1 月 13 日
    ebs 里面,如果有分摊客户都会要求最后一个倒减
    jzbax1230
        28
    jzbax1230  
       2020 年 1 月 13 日
    如果按比例乘,肯定会员 0.01 的精度问题 最后一笔减出来
    wensonsmith
        29
    wensonsmith  
       2020 年 1 月 13 日
    银行家舍入, 四舍六入五取偶。

    PHP 有 https://github.com/moneyphp/money
    racecoder00
        30
    racecoder00  
       2020 年 1 月 13 日
    Java 银行家舍入:RoundingMode.HAIL_EVEN
    zxcjqyy
        31
    zxcjqyy  
       2020 年 1 月 13 日
    我刚看淘宝某品牌手机 4199.00 元,花呗分期免手续费分 3 期,1399.67 元。
    计算器算得 4199/3=1399.666666..元,四舍五入了
    jjianwen68
        32
    jjianwen68  
       2020 年 1 月 13 日
    余数当然留给自家公司了
    mxT52CRuqR6o5
        33
    mxT52CRuqR6o5  
       2020 年 1 月 13 日 via Android
    @andy101wong 对的,这个问题和浮点数和计算机根本没关系
    Hilong
        34
    Hilong  
       2020 年 1 月 13 日 via Android
    说起这个,很早期的银行结算小数点四位后的好像就直接丢弃,有个人发现了,把这个转到了自己的账号,挣了几百上千万后被发现了
    samlee123
        35
    samlee123  
       2020 年 1 月 13 日
    @Hilong 有一部电影 有这个桥段
    pupboss
        36
    pupboss  
       2020 年 1 月 13 日
    @zxcjqyy 你说的应该是商品页面,实际生成还款账单的时候还是最后一期用减法
    opengps
        37
    opengps  
       2020 年 1 月 13 日
    第一个或者最后一个用来处理余数问题,一向如此
    mcfog
        38
    mcfog  
       2020 年 1 月 13 日
    平分: 不用总量 /份数,而是用“剩余量 /剩余份数”,就能控制误差在最多一分,算等额本息还款等场景类似,相当于把每次舍入造成的误差积累起来摊在下面一份,而不是全堆在最后或者最开头

    舍入:银行家算法 (四舍六入五成双)
    muhairen
        39
    muhairen  
       2020 年 1 月 13 日
    @Hilong 攻壳机动队就有啊
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     3016 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 97ms UTC 14:07 PVG 22:07 LAX 07:07 JFK 10:07
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86