1、JS整数表示
初级水平: 根据国际标准 IEEE 754,JavaScript 内部,所有数字都是以64位(一个字节8位)浮点数形式储存,即使整数也是如此。所以有,1 === 1.0 (二进制存储最大值=2^n-1)
中级水平:理解存储方式 结果=(-1)^s * f * 2^e,f是连续的,e不连续
- 符号位(sign),用第1位:符号位,
0表示正数,1表示负数 - 指数(exponent),用第2位到第12位(共11位):指数部分 分正负,e范围: 0--2047(2^11-1)
- 尾数(fraction),用第13位到第64位(共52位):有效数字 f是一个小数,范围: [1,2)
进一步分析:fraction是一个小数,整数部分固定为1,所以52个二进制位只存储小数部分就可以了。所以加上整数部分1后,最大数 Number.MAX_SAFE_INTEGER = Math.pow(2,53)-1;最小值类似
2、0.1+0.2===0.3//false
精度丢失可能出现在进制转换和对阶运算中
JavaScript 使用 Number 类型来表示数字(整数或浮点数),遵循 IEEE 754 标准,通过 64 位来表示一个数字(1 + 11 + 52)
1 符号位,0 表示正数,1 表示负数 s
11 指数位(e)
52 尾数,小数部分(即有效数字)
最大安全数字:Number.MAX_SAFE_INTEGER = Math.pow(2, 53) - 1,转换成整数就是 16 位,所以 0.1 === 0.1,是因为通过 toPrecision(16) 去有效位之后,两者是相等的。
在两数相加时,会先转换成二进制,0.1 和 0.2 转换成二进制的时候尾数会发生无限循环,然后进行对阶运算,JS 引擎对二进制进行截断,所以造成精度丢失。
高逼格ES6
浮点数的运算精度丢失问题。
可以引入ES6中的机器精度Number.EPSILON判定是计算误差还是数据不同。
Number.EPSILON为JavaScript可以表示的最小精度2^(-52)。
2**、0.1+0.2===0.3//false
初级水平:0.1 + 0.2 不等于0.3 ,因为Number是浮点数,表示小数的时候有精度损失。
中级水平:二进制表示整数时,十进制转二进制是除2取余法,以5为例,最后结果是101
5 / 2 = 2 余 1
2 / 2 = 1 余 0
1 / 2 = 0 余 1
二进制表示小数时,十进制转二进制是乘2取整法,只不过是从2^-1开始,以0.75为例,结果为11
0.75 * 2 = 1.5 取整 1 剩下 0.5
0.5 * 2 = 1 取整 1 剩下 0 运算结束
0.1的时候就悲催了
0.1 * 2 = 0.2 取整 0 剩下 0.2
0.2 * 2 = 0.4 取整 0 剩下 0.4
0.4 * 2 = 0.8 取整 0 剩下 0.8
0.8 * 2 = 1.6 取整 1 剩下 0.6
0.6 * 2 = 1.2 取整 1 剩下 0.2
0.2 * 2 = 0.4 取整 0 剩下 0.4
0.4 * 2 = 0.8 取整 0 剩下 0.8
0.8 * 2 = 1.6 取整 1 剩下 0.6
0.6 * 2 = 1.2 取整 1 剩下 0.2
所以有限的52个bit是无法表示0.1这种数字的,唯一的方法就是截取。
3、数字超限
Number.MAX_SAFE_INTEGER = Math.pow(2,53)-1;
高精度算法(High Accuracy Algorithm)是处理大数字的数学计算方法。在一般的科学计算中,会经常算到小数点后几百位或者更多,当然也可能是几千亿几百亿的大数字。一般这类数字我们统称为高精度数,高精度算法是用计算机对于超大数据的一种模拟加,减,乘,除,乘方,阶乘,开方等运算。对于非常庞大的数字无法在计算机中正常存储,于是,将这个数字拆开,拆成一位一位的,或者是四位四位的存储到一个数组中, 用一个数组去表示一个数字,这样这个数字就被称为是高精度数。高精度算法就是能处理高精度数各种运算的算法,但又因其特殊性,故从普通数的算法中分离,自成一家。
- 常用库:
- BigInt :
developer.mozilla.org
- bigDecimal
- json-bigint
- BigInt :