避免 Math.ceil(1.1 * 100) == 111 的最佳实践是什么?用户支付金额不对不能入账,排查了半天才发现 JS 这个逆天设计,好像别的语言也有这样的

20 小时 52 分钟前
 drymonfidelia
2984 次点击
所在节点    JavaScript
40 条回复
DOLLOR
15 小时 33 分钟前
浮点运算你换什么语言都一样。
涉及财务、金融的计算,*不能用浮点数*,要用*定点数*,这应该是程序员的常识、共识。
ntedshen
15 小时 27 分钟前
“业务需求是向上取整到整数”?
简单,
Math.ceil(Math.round(1.1*10000)/100)
然后下一届码农:md 屎山+1 (狗头
drymonfidelia
15 小时 22 分钟前
@ntedshen 我真的改成了这样 (狗头
mingl0280
12 小时 2 分钟前
涉及钱币为什么要用浮点数?
rogerer
11 小时 32 分钟前
@DOLLOR 但其实 Excel 里的财务函数也是用的浮点数,他们要求用户通过舍入函数自行控制精度。
geelaw
11 小时 21 分钟前
@drymonfidelia #20 正确的做法是金额存成 cPrice = 10000 美分,税计算为 ((cPrice * 10000 * bpTaxRate - 1) / 10000 + 1) 美分,其中 bpTaxRate 是税率的基点数(万分之几)。这里假设 cPrice 是非负数(销售),处理退款更麻烦。
geelaw
11 小时 18 分钟前
@geelaw #26 ugh 税是

(cPrice * bpTaxRate - 1) / 10000 + 1

脑子糊了
whileFalse
10 小时 47 分钟前
lz 培训班的,鉴定完毕
lovestudykid
10 小时 34 分钟前
计算机就业状况还是太好了
lithiumii
6 小时 13 分钟前
ceil 是上取整,你就算是不懂浮点数,用四舍五入这个 bug 也会少很多
lee88688
5 小时 19 分钟前
#22 的做法其实是正确的,不算什么屎山。使用二进制浮点数表示十进制浮点数在一定有效位数下可以认为是正确的,这个有效位数在 64 位浮点数下大概是 12 位。
在这些位数下转换成整数,然后将整数和小数部分取出来做处理完全没问题,楼主只需要写一些注释,后续人理解没问题的。
lee88688
5 小时 15 分钟前
多说一句,这种是将浮点数进行最终处理和简单时的做法。因为这些误差在累积计算的时候可能会让偏差越来越大,因此计算的时候还是使用浮点数需要做额外的处理,最好还是使用十进制的库计算或者用 bigint 转化为整数计算。
ahu
4 小时 5 分钟前
如 #8 所说,去看看这个网站:

location.href = 'http://' + (.1 + .2) + '.com';
Curtion
3 小时 59 分钟前
这是 IEEE754 的问题,金额相关不要用浮点数,要么使用 Decimal ,要么浮点数拆开成两个整数分开存储
mdn
3 小时 53 分钟前
采用 IEEE 754 浮点数运算的标准的语言 都会出现这个问题,包括 JavaScript Java Python 等
建议使用数学库进行运算
lyxxxh2
3 小时 35 分钟前
你不该说逆天设计,不是找喷吗。
对金额敏感,用数学库,big.js 之类。
wu67
3 小时 7 分钟前
npm install mathjs -S
EndlessMemory
3 小时 6 分钟前
0.1+0.2==0.3 ?
sastar
2 小时 49 分钟前
判断 0.1+0.2==0.3 的正确用法应该是 abs(0.1+0.2-0.3)<0.000001 ,具体在小数点后多少位取决于你对精度的要求
winglight2016
2 小时 12 分钟前
有点不理解 lz 这个代码是前端还是后端?如果是后端,从数据库设计开始就肯定用整数保存金额啊,包括银行也是这样。

如果是前端,那根本就不该去做计税这个操作——正确的设计是把用户输入全部发送到后端去计算。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1076556

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX