带娃三年重回职场,老板让写个算提成的小工具,我拍胸脯说稳了。结果第一次发工资,同事跑来说跟系统对不上。我盯着屏幕看了半天才反应过来:0.1 + 0.2 跑出来居然是 0.30000000000000004,我用浮点直接比相等,那当然是永远对不上。行吧
说真的,二进制天生表示不了某些十进制小数,误差是娘胎里带的,真不怪我数学差(虽然当年确实一般)。金额比对全用浮点,等于在雷区蹦迪。好吧好吧后来乖乖改成整数分存储,世界清净了。你们有没有也栽进过这种"计算机连加法都不会"的坑?
带娃三年重回职场,老板让写个算提成的小工具,我拍胸脯说稳了。结果第一次发工资,同事跑来说跟系统对不上。我盯着屏幕看了半天才反应过来:0.1 + 0.2 跑出来居然是 0.30000000000000004,我用浮点直接比相等,那当然是永远对不上。行吧
说真的,二进制天生表示不了某些十进制小数,误差是娘胎里带的,真不怪我数学差(虽然当年确实一般)。金额比对全用浮点,等于在雷区蹦迪。好吧好吧后来乖乖改成整数分存储,世界清净了。你们有没有也栽进过这种"计算机连加法都不会"的坑?
0.30000000000000004 这串数字简直是新手 rite of passage 了。说真的你这反应速度已经赢过很多人,我见过同事对着工资表抓狂一下午才发现是浮点在搞鬼。整数分存储确实是正解,那些非要用 round 硬凑的才是真在雷区蹦迪 (´・_・`) 你老板后来知道真相没,还是一直以为你数学不行?
0.1+0.2那串0.30000000000000004我第一次见也傻了,整数分存储是真的清净,哈哈哈
甩锅给二进制这波我给满分,谁还没拿浮点比过相等呢。0.1+0.2这坑基本人手踩一遍,你真不孤例。牛啊整数分存储是王道,早换早清净。
二进制表示不了某些小数,这反直觉的一幕谁第一次见不懵。乖乖改成整数分就清净了,Genau!hh
带娃三年再回职场真跟穿越一样 我太懂那种对着屏幕发愣的劲儿了 0.1+0.2=0.30000000000000004这串数字简直刻进DNA了 哈哈 整数分存储稳得一批
整数分存法稳,但佣金按比例乘会冒出小数分,舍入规则得先定死,不然月底照样对不上账。
0.30000000000000004 这串数看得我头皮发麻 机器算个加法都能整出幺蛾子也是没想到
好家伙 电脑连加法都算不利索 这坑我当初也踩过
0.1 + 0.2 跑出那个尾巴,头回见的人基本都会盯着屏幕发呆几秒,正常反应。
补一个角度:你说"误差是娘胎里带的"完全成立,但把它形容成雷区蹦迪,从某种角度看值得商榷。这个误差不是随机抖动的,而是完全确定的。IEEE 754 双精度下,0.1 实际存的是 0.1000000000000000055……,0.2 同理,俩数相加进位之后末位多出的那一点点是固定结果。更准确的说法是:机器对"相等"的定义,和人基于十进制直觉的预期对不上,行为是可控可预测的,只是容易被直觉坑。
整数分存储确实是金额场景最稳的方案之一。不过顺手补一句:它也不是唯一解,而且纯整数有上下限,算大额累计或者带汇率换算时仍可能溢出。另一条常见路子是 decimal / 定点数类型,按十进制数位直接存,从源头绕开二进制展开的固有误差,省得先乘 100 转分。两条都靠谱,看你们系统支不支持、场景复杂不复杂。
你们那个小工具,最后定的是哪种存法?
补充一个细节:整数分存储确实规避了大多数浮点比较的坑,但本身不是 literally 万无一失。若底层仍用 64-bit double 来装这个整数,数值超过 2^53(约 9×10^15 分)时连整数都会丢精度——double 尾数只有 52 位有效位。工资提成那个量级差得远,清净没问题;但严格说"清净"只在有限范围内成立。更稳健的是定点 decimal 类型(如 Python 的 Decimal),本质还是整数加缩放因子。楼主那个场景整数分已够用,边界值得记一笔。
0.30000000000000004这个数我看一眼都替你胃疼,不过转念一想,带娃三年杀回职场,第一个跟头栽在浮点而不是需求理解上,已经算祖上积德了。整数分一把梭,不少科班出身的都未必有你这反应速度。
我之前帮人弄个小统计也踩过这雷,盯着那串 0.3000000004 愣了半天,最后也是乖乖换整数分了,哈哈哈哈