当前位置 : 主页 > 网络编程 > JavaScript >

JS数字精度丢失的原因及解决方案

来源:互联网 收集:自由互联 发布时间:2023-01-19
目录 前言 精度丢失 原因 如何将整数从十进制转换为二进制 将小数从十进制转换为二进制 解决方案 第三方库 Decimal bignumber 变成整数 总结 前言 在JavaScript中计算两个十进制数的和,有
目录
  • 前言
  • 精度丢失
  • 原因
    • 如何将整数从十进制转换为二进制
    • 将小数从十进制转换为二进制
  • 解决方案
    • 第三方库
    • Decimal
    • bignumber
    • 变成整数
  • 总结

    前言

    在JavaScript中计算两个十进制数的和,有时候会出现令人惊讶的结果,相信这个大家也都知道了!

    精度丢失

    例如,我们在计算0.1 + 0.1得到的结果是0.2,但是计算0.1 + 0.2的结果并不是0.3,而是0.30000000000000004

    这种现象不仅出现在加法,在减法中也会出现类似的结果。

    例如1.2 - 1的结果是0.19999999999999996

    不过这并不是JavaScript独有的,其他编程语言也会存在同样的问题。

    例如在Python环境下输出。

    print(.1 + .2) 

    得到的结果同样是:0.30000000000000004

    原因

    这个问题的主要原因是计算机将数据存储为二进制。

    如何将整数从十进制转换为二进制

    十进制整数可以通过将其除以 2 转换为二进制。取商,并继续除以 2,直到达到零。

    每次执行此除法时,请记下余数。现在反转余数列表,得到二进制形式的数字。

    举个例子,我想把29转成二进制:

    29÷2=14余1

    14÷2=7余0

    7÷2=3余1

    3÷2=1余1

    1÷2=0余1

    代表十进制 29 的二进制数是11101.

    例如:

    • 1 也就是1

    • 10 也就是1010

    将小数从十进制转换为二进制

    十进制小数转换成二进制小数采用"乘2取整,顺序排列"法。具体做法是:用2乘十进制小数,可以得到积,将积的整数部分取出,再用2乘余下的小数部分,又得到一个积,再将积的整数部分取出,如此进行,直到积中的小数部分为零,此时0或1为二进制的最后一位。或者达到所要求的精度为止。

    举个例子:我想把0.375转成二进制:

    0.375*2=0.75 得到0

    0.75*2=1.5得到1

    0.5*2=1 得到1,小数没了,结束。最终转为二进制是0.011

    例如:

    • 0.1 也就是0.0001100110011001100110011001100110011001100110011001101
    • 0.2 也就是0.001100110011001100110011001100110011001100110011001101

    并非每个十进制数都可以用这种二进制格式完美表示,因为有些数字可能转成

    JavaScript 在计算时,会先将10进制转为二进制,在进行计算。

    0.00011001100110011001100110011001100110011001100110011010 +
    0.0011001100110011001100110011001100110011001100110011010 =
    0.0100110011001100110011001100110011001100110011001100111

    这里得到的结果0.0100110011001100110011001100110011001100110011001100111再转换成十进制就是0.30000000000000004

    解决方案

    第三方库

    Decimal

    x = new Decimal(0.1)
    y = x.plus(0.2) 

    bignumber

    x = new BigNumber(0.1)
    y = x.plus(0.2)    

    变成整数

    主要思想是:将小数先转换成拆分两个字符串,然后计算小数部分的字符串的长度,然后利用这个长度将小数变成整数!

    function add(num1, num2) {
      const num1Len = (num1.toString().split('.')[1] ).length;
      const num2Len = (num2.toString().split('.')[1] ).length;
      const maxLen = Math.pow(10, Math.max(num1Len, num2Len));
      return (num1 * maxLen + num2 * maxLen) / maxLen;
    }

    总结

    到此这篇关于JS数字精度丢失的原因分析及解决的文章就介绍到这了,更多相关JS数字精度丢失内容请搜索自由互联以前的文章或继续浏览下面的相关文章希望大家以后多多支持自由互联!

    上一篇:利用Math.js解决JS计算小数精度丢失问题
    下一篇:没有了
    网友评论