Number_js小数计算精度问题(mathjs)


在js中是不区分浮点型和整数型,只要是数字即为number类型。

在计算机中,所有的数据都是以二进制的形式进行存储。

(小数)十进制转化为二进制

小数十进制转化为二进制采用乘2取整法至值为0或无限循环为止。

举例说明-> 0.1

将0.1转化为二进制进行存储

0.1*2=0.2 --------0
0.2*2=0.4 --------0
0.4*2=0.8 --------0
0.8*2=1.6 --------1
0.6*2=1.2 --------1
------开始循环------
0.2*2=0.4 --------0
0.4*2=0.8 --------0
0.8*2=1.6 --------1
0.6*2=1.2 --------1

因此0.1转化为二进制为 0.00011 0011 0011 0011 …

举例说明 ->0.2
0.2*2=0.4 --------0
0.4*2=0.8 --------0
0.8*2=1.6 --------1
0.6*2=1.2 --------1
------开始循环------
0.2*2=0.4 --------0
0.4*2=0.8 --------0
0.8*2=1.6 --------1
0.6*2=1.2 --------1

因此0.2转化为二进制为 0.0011 0011 0011 0011 …

小数存储

js中的数字类型相当于其他强类型语言中的double类型,也就是双精度浮点类型。采用64位二进制数表示一个number类型数据。这64位的二进制数作用如下:
在这里插入图片描述

  • 符号位:用来表示数字的正负,0为正数,1为负数
  • 指数位:一般都用科学计数法表示数值大小,但是这里一般都是2进制的科学计数法,表示2的多少次方
  • 小数位:存储小数
举例说明小数存储过程 --> 0.1存储
  • [1] 将0.1转化为2进制

    0.1转化为二进制为 0.00011 0011 0011 0011 …

  • [2] 存储小数采用 科学计数法IEEE745标准, 默认所有的该数值都转为1.xxxxx这种格式

    tips:最终所有数据都是1.xxxx ,数据格式统一,因此存储时省略1,这样做可以多存储一位小数!

    0.1存储为这种格式为 1.1001 1001 1001 1… * 2 的-4次方

  • [3] 存储过程

    • (1)符号位

      正数: 0

    • (2)指数位

      指数共占11位, 取值分别为00000000000~11111111111
      将中间值 11111111111/2 01111111111作为0
      正值++
      -1 01111111110
      -2 01111111101

      负值–
      1 10000000000
      2 10000000001

      0.1的指数位为-4 转化为二进制为01111111011

    • (3)小数位存储:只能存储52位小数位, 因此将小数位保留为52位

      注意: 存储过程中类似十进制的四舍五入:若是末尾为1,则前一位加1,若是末尾为0,则不变

      0.1 的小数位为
      1001100110011001100110011001100110011001100110011001…
      末位进位
      1001100110011001100110011001100110011001100110011010

    • 最终存储结果为:0011111110111001100110011001100110011001100110011001100110011010

      因此小数在存储的时候精度存在丢失的可能

小数计算

小数在计算时是将数据转化为对应的二进制再进行计算

在计算浮点数相加时,需要先进行 “对位”,将较小的指数化为较大的指数,并将小数部分相应右移。==> 省略后不要忘记进位哦~

举例说明小数计算 0.1+0.2

0.1转化为二进制为 1.1001 1001 1001 … * 2 的-4次方
0.2转化为二进制为 1.1001 1001 1001 … * 2的-3次方

两者次方不一样先进行对位

0.11001100110011001100110011001100110011001100110011010
1.1001100110011001100110011001100110011001100110011010

结果
10.0110011001100110011001100110011001100110011001100111 0
转化为标准形式
1.0011001100110011001100110011001100110011001100110011 10
保留52位小数
1.0011001100110011001100110011001100110011001100110100
存储
0 01111111011 0011001100110011001100110011001100110011001100110100

小数存储总结

也就是说小数在存储的过程中失去一次精度,在计算的时候又失去一次精度,因此在计算过程中造成结果不准确同时小数位超多;

那么如何解决小数计算时失精的问题呢?

  1. 可以将小数转化为整数进行计算
  2. 使用Number的toFixed方法保留固定小数位 (没有小数也会补0)
  3. 使用插件mathjs解决

mathjs插件

  • 下载

    npm install mathjs
    
  • 配置

    import {
          
           create, all } from 'mathjs'
    const config = {
          
          
      number: 'BigNumber', // 可选值:number BigNumber
    }
    const math = create(all, config)
    

    注意若是 number配置项为 BigNumber可以解决小数失去精度问题,若是值为number 则小数计算仍然失精!

  • 使用evaluate方法解决失精问题

    math.evaluate(0.1+0.2) // 0.30
    

猜你喜欢

转载自blog.csdn.net/qq_43260366/article/details/129625970