19新版教育培训风格演示站
标题: js 中的 number 为何很怪异 [打印本页]
作者: DeJay王健 时间: 2019-1-11 12:09
标题: js 中的 number 为何很怪异
对于 JavaScript 开发者来说,或多或少都遇到过 js 在处理数字上的奇怪现象,比如:
- > 0.1 + 0.2
- 0.30000000000000004
- > 0.1 + 1 - 1
- 0.10000000000000009
- > 0.1 * 0.2
- 0.020000000000000004
- > Math.pow(2, 53)
- 9007199254740992
- > Math.pow(2, 53) + 1
- 9007199254740992
- > Math.pow(2, 53) + 3
- 9007199254740996
复制代码
如果想要弄明白为什么会出现这些奇怪现象,首先要弄清楚 JavaScript 是怎样编码数字的。
1. JavaScript 是怎样编码数字的
JavaScript 中的数字,不管是整数、小数、分数,还是正数、负数,全部是浮点数,都是用 8 个字节(64 位)来存储的。
一个数字(如 12、0.12、-999)在内存中占用 8 个字节(64 位),存储方式如下:
- 0 - 51:分数部分(52 位)
- 52 - 62:指数部分(11 位)
- 63:符号位(1 位:0 表示这个数是正数,1 表示这个数是负数)
符号位很好理解,用于指明是正数还是负数,且只有 1 位、两种情况(0 表示正数,1 表示负数)。
其他两部分是分数部分和指数部分,用于计算一个数的绝对值。
1.1 绝对值计算公式
- 1: abs = 1.f * 2 ^ (e - 1023) 0 < e < 2047
- 2: abs = 0.f * 2 ^ (e - 1022) e = 0, f > 0
- 3: abs = 0 e = 0, f = 0
- 4: abs = NaN e = 2047, f > 0
- 5: abs = ∞ (infinity, 无穷大) e = 2047, f = 0
复制代码
说明:
- 这个公式是二进制的算法公式,结果用 abs 表示,分数部分用 f 表示,指数部分用 e 表示
- 2 ^ (e - 1023) 表示 2 的 e - 1023 次方
- 因为分数部分占 52 位,所以 f 的取值范围为 00...00(中间省略 48 个 0) 到 11...11(中间省略 48 个 1)
- 因为指数部分占 11 位,所以 e 的取值范围为 0(00000000000) 到 2047(11111111111)
从上面的公式可以看出:
- 1 的存储方式:1.00 * 2 ^ (1023 - 1023)(f = 0000..., e = 1023,... 表示 48 个 0)
- 2 的存储方式:1.00 * 2 ^ (1024 - 1023)(f = 0000..., e = 1024,... 表示 48 个 0)
- 9 的存储方式:1.01 * 2 ^ (1025 - 1023)(f = 0100..., e = 1025,... 表示 48 个 0)
- 0.5 的存储方式:1.00 * 2 ^ (1022 - 1023)(f = 0000..., e = 1022,... 表示 48 个 0)
- 0.625 的存储方式:1.01 * 2 ^ (1021 - 1023)(f = 0100..., e = 1021,... 表示 48 个 0)
1.2 绝对值的取值范围与边界从上面的公式可以看出:
1.2.1 0 < e < 2047当 0 < e < 2047 时,取值范围为:f= 0, e = 1 到 f= 11...11, e = 2046(中间省略 48 个 1)
即:Math.pow(2,-1022) 到 ~= Math.pow(2, 1024) - 1(~= 表示约等于)
这当中,~=Math.pow(2, 1024) - 1 就是 Number.MAX_VALUE 的值,js 所能表示的最大数值。
1.2.2 e = 0, f > 0当 e = 0, f > 0 时,取值范围为:f= 00...01, e = 0(中间省略 48 个 0) 到 f = 11...11, e = 0(中间省略 48个 1)
即:Math.pow(2,-1074) 到 ~= Math.pow(2, -1022)(~= 表示约等于)
这当中,Math.pow(2,-1074) 就是 Number.MIN_VALUE 的值,js 所能表示的最小数值(绝对值)。
1.2.3 e = 0, f = 0这只表示一个值 0,但加上符号位,所以有 +0 与 -0。
欢迎光临 19新版教育培训风格演示站 (http://47.100.112.22/demo/train/) |
Powered by Discuz! X3.5 |