携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第10天,点击查看活动详情。
快问快答
64 位操作系统能表示的最大整数是多少?
64 位有符号整型能表示的最大值为 2 ^ 63 - 1 = 9223372036854775807,这是一个 19 位数。
MySQL 数据库的 id 字段经常用 19 位的长整型表示。
JS 能表示的最大数是多少?
JS 能表示的最大整数:Number.MAX_SAFE_INTEGER = 9007199254740991,约为 9e16
JS 能表示的最大正数:Number.MAX_VALUE = 1.7976931348623157e+308,约为 1.79e308
为什么 JS 的最大整数不是 19 位,而是 16 位?
JS 的正整数是用的尾数的长度表示,由于尾数是 52 位,加上整数的 1 位,它能表示的最大整数是 2 ^ 53 - 1 = 9007199254740991,是 16 位的。
为什么 JS 的最大正数是 1.79e308?
这个数是双精度浮点数所能表示的最大正值。
为什么 JS 有尾数的概念?
JS 内的数字运算采用 IEEE 754 标准,IEEE 二进制浮点数算术标准是20世纪80年代以来最广泛使用的浮点数运算标准。
存储形式:
- Bit 63:最高有效位被指定为符号位
- Bit 62-52:次高有效的11位是指数位
- Bit 51-0:低有效的52位尾数存储有效数的小数部分
因为 JS 的整型和浮点型在计算过程中可以随时自动切换,整型在 JS 里也是用浮点数的解构存储的,放在尾数的部分,所以 JS 的数字运算方式实际是 IEEE 754 的运算方式。
为什么 0.1 + 0.2 != 0.3 ?
JS 内的浮点数计算在进制转换和对阶运算中会导致结果偏差。
基础原理
浮点数相加,需要先转换成二进制,然后比较阶码是否一致,一致则尾数直接相加,不一致需要先对阶,小阶向大阶看齐(即把小阶的指数调成和大阶的一样大),并把它的尾数向右移相应位数,超出部分采用 “四舍五入” 形式截断进位。
进制转换(十进制 -> 二进制)
0.1 -> 0.0001100110011001... -> 1.10111001100... * 2 ^ -4
0.2 -> 0.0011001100110011... -> 1.10111001100... * 2 ^ -3
对阶运算
0.1 的小数点右移一位变成 1.10111001100... * 2 ^ -3
右移一位导致尾数需要截断,由于最后一位刚好是 0,这里直接舍弃。
再相加时,发生了进位,变成了 53 位,超过尾数 52 位的范围,所以阶码再进一位,即指数 + 1(乘以2),两数和的尾数右移一位,即除以2,由于尾数最后一位是1,四舍五入,舍弃最后一位后再加上 1,结果就变成了
1011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0100 * 2 ^ -2
进制转换(二进制 -> 十进制)
转换成 0.30000000000000004
结果
0.1 + 0.2 != 0.3
怎么判断 0.1 + 0.2 = 0.3?
ES6 新增了 Number.EPSILON 属性,使用 0.1 + 0.2 - 0.3 < Number.EPSILON 判断,Number.EPSILON 表示一个很小的小数,差值小于这个数则认为两者相等。