>

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

user2 • 11 次点击

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

user1

基础没学好,回去重修。


解决方法就是钱永远别用小数。

user2

第一反应精度丢失问题,转念想怎么会差这么多, 仔细一看,ceil ,你确定这不是设计如此有人贪这差值吗,

user3

计算金融不要用二进制浮点数,二进制浮点数的设计就没法精确表示十进制有理数。用十进制浮点数或者定点数,因为金融业务很少用到分以下,用定点数的比较多。十进制浮点数的支持状态也不太好。

user1

biginit

user2

“1.1” 是十进制,当这个值转为数字的时候是无限循环小数 1.0001100110011001100110011…
舍入后就是 1.0001100110011001100110011001100110011001100110011010, 注意最后一位是向上舍入的。
所以最开始从 “1.1” 这个字符串解析到数字的时候就已经不准确了。

属实是计算机基础不扎实。

user3

内部数据应该用分为单位的整数吧,显示的时候转换

user1

npm install decimal.js

user2

既然用了浮点数 ceil ,哪就不得不得不掏出祖传的 0.30000000000000004.com

php -r var_dump(ceil(1.1*100));
//float(111)

user3

bignumber.js

user1

凡是涉及金额,都不能简单计算。

一个金额,一个日期,这两个是很典型新手误区,表面上看起来没什么,实际上都藏着大坑。

user2

金额永远别用浮点数 用 decimal

user3

二进制只能近似存储小数,详细重新学习 IEEE754 ,还有以前面试区分培训和科班第一个就让说 IEEE754 ,不知道的一定是培训出来的,因为培训班不会说什么浮点数底层怎么实现,而是会说金额不让用 double ,科班必定知道,计组第一章就是吧

user1

只用数据库计算

user2

string 或者整形存储,计算时得注意精度丢失问题

user3

" JS 这个逆天设计",很野的说法

user1

与其说语言的逆天设计,不如说只知道给金额用浮点数的程序员比较逆天吧。

user2

这个不是常见的面试题么,没见过嘛?

改用 Decimal.js 吧。https://www.npmjs.com/package/decimal.js/v/10.4.3

其他语言也有类似的库,推荐直接用这种方案来做计算。

user3

https://github.com/kdeldycke/awesome-falsehood
建议任何程序员写代码前都读一遍

涉及金额,只设计人民币,可以考虑 decimal ,最好是专门的类型

user1

测了下 1.1 * 100 == 110.00000000000001 向上取整所以是 111 没问题啊。。。

问题在于 LZ 你为啥要向上取整啊。。round 不行么。

user2

@est 因为商品价格 100 美元,税 10%,业务需求是向上取整到整数

1
2
3
20 / 页
总数 422