JS中使用IEEE-754规定的双精度浮点数,所有的算法也都符合IEEE-754规定的双精度浮点数运算。
双精度浮点数是一种64位(64 bit)的二进制数字格式。包括3个组成部分:
- 符号位 1位
- 阶码(指数部分) 11位
- 尾数(有效数)53位(实际存储52位)
其中,符号位0表示正值,1表示负值;
指数部分存储为无符号数字,可表示的十进制数字范围为[0, 2047]。由于指数可为正为负,因此在运算中引入了指数偏差量(exponent bias),在双精度浮点数中这个值为1023(2^10 - 1),在指数运算中大于1023的表示指数为正,小于1023的表示指数为负。标准有效数的指数范围为[-1022, 1023],指数-1023(全0)为0(signed zeros)和次正常数(subnormal numbers)保留,指数+1024(全1)为无穷数(infinities)和NaNs保留。
标准有效数在存入IEEE-754二进制交换格式中隐去了值总是为1的前导位(hidden bit),因此尾数的实际精度是53位。
事实上,11位宽度的阶码允许表示10^-308到10^308之间的数字(Number.MAX_VALUE),并且通过降低精度,允许表示的最小正值可以达到5E-324(Number.MIN_VALUE)。而53位的尾数能够表示的精度的最大值为2^53(Math.pow(2, 53)),IEEE-754对15~17位的有效的十进制数字的精度做出规定:
如果一个最高15位有效数位的十进制字符串转换为IEEE-754双精度表示,再转换回同样位数的十进制字符串,最终结果应该和原始字符串一致;
如果一个IEEE-754双精度浮点数转换为一个最少17位有效数位的十进制字符串,再转换回双精度表示,最终结果比喻和原始数值一致。
JS在ES6中首次定义了最大的安全整数常量(Number.MAX_SAFE_VALUE)和最小的安全整数常量(Number.MIN_SAFE_VALUE)。并给出了安全整数的定义:
- 能被精确表示的IEEE-754双精度数字
- 在IEEE-754任何舍入模式中没有其他数字被舍入为该数
为什么最大安全整数常量为2^53 - 1,因为2^53虽然是能够被表示的精度的最大值,但是并不安全。
9007199254740992 == 9007199254740993 //true
复制代码
最后,在大数相加substr
算法中使用的是-14,个人理解是因为规范明确给出了15位的十进制字符串转换能够确保精度,因此即使最大14位发生进位精度也是能够确保的,而15位发生进位时也许会遇到一些不可知的情况。