InfoQ 推荐 ( ) • 2021-09-18 15:44
0:指数位全 0,尾数位也全是0,则表示 ±0∞:指数全 1,尾数全 0,则表示 ±∞,也就是 Number.POSITIVE_INFINITY 和 Number.NEGATIVE_INFINITYNaN:指数全1,尾数不全为 0,则表示非数字 NaNNumber.MIN_VALUE 和非规约数我们来看一个相对正常的数字 5e-324,这是 Number.MIN_VALUE 的值:按照上文规约化浮点数的公式,规约化浮点数,指数部分范围 [-1022, 1023]。
小结上文从求 1.7976931348623157e+308 的思路出发,对 Number.MAX_VALUE 和 Number.MIN_VALUE 进行推导,总结如下:我们可以把 64 位浮点数分为 3 类:1、特殊值0:指数位全 0,尾数位也全是 0,则表示 ±0∞:指数全 1,尾数全 0,则表示 ±∞NaN:指数全 1,尾数不全为 0,则表示非数字 NaN2、规约形式的浮点数指数位不全为 0,且不全为 1,此时偏移量为 1023,指数范围 [-1022, 1023]3、非规约形式的浮点数指数位全 0,尾数不全为 0,此时偏移量为 1022,指数部分只为 -1022还有谁其实还有几个神秘数字,有了上面的公式,我们都能够推导出来,我们一个个看:最大安全整数 Number.MAX_SAFE_INTEGERNumber.MAX_SAFE_INTEGER 的值是 9007199254740991,我们分析一下,规约化浮点数,尾数部分有 52 位,最大安全整数应该是小数部分全为 1,指数部分为 52:用 JavaScript 来验证一下2**53 - 1 // 9007199254740991。
没问题,最后一个神秘数字搞定, 2.220446049250313e-16 就是 回到那道经典题目 “0.1 + 0.2 为什么等于 0.30000000000000004”十进制小数转二进制先回顾一下十进制小数转 2 进制方法:“乘2取整,顺序排列”法:0.1 转换二进制:0.2 转换二进制:可以看到,0.1 和 0.2 转为二进制都是无限循环小数,转为 64 位浮点数会有精度损失,我们来转换一下:0.1 在 64 位浮点数中的存储使用 (1019).toString(2) 可以算出 1019 的二进制为 1111111011 :共 10 位,头部补 0 得到 11 位指数 01111111011:再来看尾数部分:1 开始,0111 循环,到了第 52 位为 1,但是需要额外注意,第 53 位仍然是 1,舍去需要进 1,尾数部分变为了(为了方便阅读,使用了 ES2021 的数值分隔符") 1_0011_0011_0011_0011_0011_0011_0011_0011_0011_0011_0011_0011_010:因此,0.1 在 64 位浮点数上存储如下:0.2 在 64 位浮点数中的存储使用 (1020).toString(2) 可以算出 1020 的二进制为 1111111100 :共 10 位,头部补 0 得到 11 位指数 01111111100:尾数部分和 0.1 完全一致,也需要进 1,尾数部分为 1_0011_0011_0011_0011_0011_0011_0011_0011_0011_0011_0011_0011_010 ... 阅读全文