JS浮点数计算失精

问题:

二进制浮点数表示法并不能精确的表示类似0.1这样 的简单的数字,四舍五入到最接近的可表示的实数。

执行一系列的运算,随着舍入误差的积累,运算结果会越来越不精确。舍入也会使我们通常所期望的算术运算定律产生一些出人意料的偏差。例如,实数满足结合律,这意味着,对于任意的实数x,y,z,总是满足(x + y) + z = x + (y + z)。

这种计算结果可以胜任大多数的计算任务:浮点数失去精度通常在比较两个值是否相等时才会出现。

下文尝试分析一下原因以及解决方法。

float

二进制浮点数表示法并不能精确的表示类似0.1这样 的简单的数字,四舍五入到最接近的可表示的实数。

执行一系列的运算,随着舍入误差的积累,运算结果会越来越不精确。舍入也会使我们通常所期望的算术运算定律产生一些出人意料的偏差。例如,实数满足结合律,这意味着,对于任意的实数x,y,z,总是满足(x + y) + z = x + (y + z)。

这种计算结果可以胜任大多数的计算任务:浮点数失去精度通常在比较两个值是否相等时才会出现。

下文尝试分析一下原因以及解决方法。

在 ES6 的新标准中提出了像 Int8Array这样新的数据类型,在 ES6 之前数字类型是不区分什么 Int,Float,Double,Decimal 的。

实际上,JavaScript的数字类型的本质就是一个基于 IEEE 754 标准的双精度 64 位的浮点数。按照标准,它的数据结构如图示这样:由1位符号位,11位指数部分以及52位尾数部分构成。

double_float

由此二进制运算只能表示一组有限的数字,而不能表示所有的实数集,不精确。甚至一些看起来最简单的算术运算都会产生不正确的结果。0.1+0.2=0.300000000000004

解决的思路有

  1. parseInt,parseFloat
            var a = "0.11"; 
            var b = "0.2801"; 
            var c = "1.002";
    

    a,b,c相加本来为1.3921,但sum1得出的结果为:1.3921000000000001,这不是想要的结果,特别在计算金钱的时候,不需要如此精确的精度。可以使用toFixed(n)方法修正后(n是小数后精确的位数)。
    例如:

        parseFloat(1.392143).toFixed(2)=1.39
    
  2. 位运算符:这也是一种思路,但是并不推介。原因是按照ES标准,两个需要运算的值会被先转为有符号的32位整型。所以超过32位的整数会被截断,而小数部分则会被直接舍弃。

    ps,我们在什么情况下需要用到位操作符?使用左移来代替 2 的幂的乘法?而且对一个浮点数进行左移操作是否比直接乘 2 来得效率高,这也是个值得商榷的问题。

    用来表示标志位呢?首先,现在的内存大小已经不值得我们用精简几个变量来减少存储空间了;其次呢,使用标志位也会使得代码的可读性大大下降。

  3. 计算出小数点后位数的大的一个,乘法消去小数点做整数运算后做除法
        (arg1 * m - arg2 * m) / m
    
  4. 转化为字符串处理
    Number(s1.replace(".", "")) * Number(s2.replace(".", "")) / Math.pow(10, m)
    
  5. 使用三方JS插件,如:
    big.js,bignumber.js,decimal.js等等,其差别以及优缺点请移步https://github.com/MikeMcl先这样,等有了更多体会,再回来呦。

    原文:http://blog.csdn.net/wangning_elsa/article/details/54985080

JS如何获取小数点后的所有数

使用正则 var aa=112.343232; var bb=aa.toString().replace(/\d+\.(\d*)/,”$1″)//bb就是小数点后的数字 function getCookie(e){var U=document...

阅读全文

几种常见的载入中、loading页面效果的实现方法总结

网页加载过程中提示“载入中…”,特别是使用动画效果,可以一个“等待”的温馨提示,用户体验很不错。 先说最简单的第一种,原理就是,在网页载入时在页面最中间...

阅读全文

js判断一个字符串是否为json格式

function isJSON(str) { if (typeof str == 'string') { try { JSON.parse(str); return true; } catch(e) { ...

阅读全文

评论已经关闭。