• JavaScript实现浮点数运算问题


    作者:趁你还年轻233
    链接:https://www.jianshu.com/p/407b6c3677f5
    来源:简书
    类型:转载

    这篇博客将主要提供几种解决小数精度丢失问题的JavaScript类库的代码示例,以及简单的原生EcmaScript方法的代码示例。

    一丶类库部分

    math.js

    math.js是JavaScript和Node.js的一个广泛的数学库。支持数字,大数,复数,分数,单位和矩阵等数据类型的运算。

    官网:http://mathjs.org/
    GitHub:https://github.com/josdejong/mathjs

    0.1+0.2 ===0.3实现代码:

    var math = require('mathjs')
    console.log(math.add(0.1,0.2))//0.30000000000000004
    console.log(math.format((math.add(math.bignumber(0.1),math.bignumber(0.2)))))//'0.3'
    

    decimal.js

    为 JavaScript 提供十进制类型的任意精度数值。

    官网:http://mikemcl.github.io/decimal.js/

    GitHub:https://github.com/MikeMcl/decimal.js

    0.1+0.2 ===0.3实现代码:

    var Decimal = require('decimal.js')
    x = new  Decimal(0.1)
    y = 0.2
    console.log(x.plus(y).toString())//'0.3'
    

    bignumber.js

    用于任意精度算术的JavaScript库。

    官网:http://mikemcl.github.io/bignumber.js/

    Github:https://github.com/MikeMcl/bignumber.js

    var BigNumber = require("bignumber.js")
    x = new BigNumber(0.1)
    y = 0.2
    console.log(x.plus(y).toString())//'0.3'
    

    big.js

    用于任意精度十进制算术的小型快速JavaScript库。
    官网:http://mikemcl.github.io/big.js/
    Github:https://github.com/MikeMcl/big.js/

    var Big = require("big.js")
    x = new Big(0.1)
    y = 0.2
    console.log(x.plus(y).toString())//'0.3'
    

    number-precision.js

    用于任意精度十进制算术的小型快速JavaScript库。
    官网:https://github.com/nefe/number-precision/
    Github:https://github.com/nefe/number-precision/

    import NP from 'number-precision'
    NP.strip(0.09999999999999998); // = 0.1
    NP.plus(0.1, 0.2);             // = 0.3, not 0.30000000000000004
    NP.plus(2.3, 2.4);             // = 4.7, not 4.699999999999999
    NP.minus(1.0, 0.9);            // = 0.1, not 0.09999999999999998
    NP.times(3, 0.3);              // = 0.9, not 0.8999999999999999
    NP.times(0.362, 100);          // = 36.2, not 36.199999999999996
    NP.divide(1.21, 1.1);          // = 1.1, not 1.0999999999999999
    NP.round(0.105, 2);            // = 0.11, not 0.1
    

    有一个需要注意的点,使用类库此时输出的0.3是String类型,因此若想保持为Number类型,可使用parseFloat()方法。

    还有一个注意点,在本地install测试的时候,npm i mathjs -g ,require是也要require('mathjs'),而不是带点的math.js,因为josdejong这哥们在创建项目的时候就命名为mathjs,而同时拥有上述decimal.js, bignumber.js和big.js的MikeMcl,项目名字就带了dot,因此安装和引入时,都是xxx.js的形式。

    如何在这三个类库之间做选择,还需要大家自己根据具体情况具体分析,我在这里就不赘述了。

    最后,教大家一个线上直接测试的网站,https://npm.runkit.com,子路径输入想要测试的Node.js package名,就可以实现在线测试包中的api了。
    例如:
    math.js:https://npm.runkit.com/mathjs
    big.js:https://npm.runkit.com/big.js

    二、原生方法

    原生方法解决浮点数运算的解决方案有很多,这里给出一种目前常用的解决方案, 在判断浮点数运算结果前对计算结果进行精度缩小,因为在精度缩小的过程总会自动四舍五入。使用Number.prototype.toFixed()方法。

    toFixed() 方法使用定点表示法来格式化一个数,会对结果进行四舍五入。语法为:

    JavaScript 代码:
    numObj.toFixed(digits)
    参数 digits 表示小数点后数字的个数;介于 0 到 20 (包括)之间,实现环境可能支持更大范围。如果忽略该参数,则默认为 0。

    返回一个数值的字符串表现形式,不使用指数记数法,而是在小数点后有 digits 位数字。该数值在必要时进行四舍五入,另外在必要时会用 0 来填充小数部分,以便小数部分有指定的位数。 如果数值大于 1e+21,该方法会简单调用 Number.prototype.toString()并返回一个指数记数法格式的字符串。

    特别注意:toFixed() 返回一个数值的字符串表现形式。

    具体可以查看 MDN中的说明,那么我们可以这样解决精度问题:

    JavaScript 代码:

    parseFloat((数学表达式).toFixed(digits)); // toFixed() 精度参数须在 0 与20 之间
    // 运行
    parseFloat((0.1 + 0.2).toFixed(10))//结果为0.3
    parseFloat((0.3 / 0.1).toFixed(10)) // 结果为 3  
    parseFloat((0.7 * 180).toFixed(10))//结果为126
    parseFloat((1.0 - 0.9).toFixed(10)) // 结果为 0.1   
    parseFloat((9.7 * 100).toFixed(10)) // 结果为 970 
    parseFloat((2.22 + 0.1).toFixed(10)) // 结果为 2.32
    

    在Browser环境精度参数允许0~100位之间(包括100),测试版本为Chrome62(64位)和Firefox56 (32 位)。
    在Nodejs环境中,只能是0~20之间,测试版本为v6.9.5。

    其次就是toFixed()的浏览器兼容性讨论,MDN给出的结果全部是YES,无论desktop端还是mobile端,也就是说不用担心toFixed()的兼容性问题(ie8- 我们不做讨论)。

    desktop端:

    img

    mobile端:

    img

    Thanks:
    http://www.css88.com/archives/7340#more-7340
    https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed

  • 相关阅读:
    Android 使用ViewPager结合PhotoView开源组件实现网络图片在线浏览功能
    Android教程 -06 Activity的生命周期
    Android教程 -05 Android6.0权限的管理
    Android 设置ImageView宽度固定,其高度按比例缩放适应
    一技压身,天下行走
    解析P2P金融的业务安全
    Android Listview中Button按钮点击事件冲突解决办法
    Android 动态设置TextView的drawableLeft等属性
    Android教程 -04 启动其它Activity,静态工厂设计模式传递数据
    瞬息之间与时间之门
  • 原文地址:https://www.cnblogs.com/Scooby/p/12558682.html
Copyright © 2020-2023  润新知