Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

浮点数计算精度问题与mathjs #34

Open
jsonz1993 opened this issue Oct 20, 2021 · 0 comments
Open

浮点数计算精度问题与mathjs #34

jsonz1993 opened this issue Oct 20, 2021 · 0 comments

Comments

@jsonz1993
Copy link
Owner

浮点数精度问题

众所周知,js的浮点数计算一直被人诟病,最经典莫过于 0.1 + 0.2 !== 0.3
原因也很简单,计算机在做运算的时候都会把十进制转化为二进制来处理

0.1 -> 0.0001100110011001...(无限)
0.2 -> 0.0011001100110011...(无限)
0.1 + 0.2 -> 0.0100110011001100110011001100110011001100110011001100(IEEE 754)
再把二进制转为十进制就变成了: 0.30000000000000004

更详细的可以看 JavaScript 浮点数运算的精度问题

问题

我们已经熟知直接在浏览器端用js做计算经常出现各种奇怪问题,所以做系统的时候肯定都会提前考虑过这些,比如

  • 计算逻辑尽可能放在后端处理,避免多端处理重复与差异
  • 做的时候用一些小技巧,比如先乘后操作,避免出现浮点数
  • 用mathjs,最省心省力的方式

目前系统做投资相关业务,所以避免不了有大量数值类需要处理,所以在项目开始的时候,就引入mathjs作为计算的库。
但是前几天发现一个bug,是数值展示与实际的数值对不上,而且查了代码,这里确实有用到Mathjs计算的。

后面排查了才发现,mathjs 默认使用的是number 类型,我们需要手动去设置为 BigNumber 才能避免上面浮点数精度问题
image
至于原因,mathjs认为如果我们计算结果取四舍五入,是不会影响实际的展示效果的。

确实平时页面上数据的展示都是小数点后x位(2~6位),如果按照四舍五入去截取不会出现问题,系统的这个bug出现的原因就在于这一块的展示逻辑产品说直接截断小数点后两位,而不是采用四舍五入,所以就会导致计算结果和实际结果有差异。

-0.0006 * 10000 -> -5.99

解决方案

既然已经知道问题了,解决起来也方便,由于mathjs没办法做到全局配置
他的配置是要通过 create 接口去创建一个新的实例,也就是说,如果你一个地方用到,那你就要手动去create 一个 bigNumber类型的mathjs实例。
目前老项目有多个地方用到mathjs,一个一个地方去改是不可能的,所以直接配了一个 webpack.alias,把mathjs引到自己写的一个文件里,在文件中再去统一配置mathjs,相当于创建了一个mathjs单例。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant