Appearance
IEEE 754
现代计算机中的浮点
基本格式
单精度
占用 32 位(4 字节)的二进制格式,其有效数字为 24 位(约 7 个十进制数)的精度
双精度
占用 64 位(8 字节)的二进制格式,其有效数字为 53 位(约 15 - 17 个十进制数)的精度
双重扩展
二进制格式至少占用 79 位(约 19 个十进制数)的精度
四倍精度
128 位(16 字节)的二进制格式(约 34 个十进制数)的精度
Decimal64 decimal128
十进制舍入
半精度
binary16 16 位浮点值
浮点数范围
64 位双精度 = 具有 53 位(包含一个隐含位)1 个符号位 11 个指数位的系数(指数可以表示的数 2^-1022 ≈ 2×10^-308 - 2^1024 ≈ 2 x 10^308)
字节序(Endian)
浮点数以大字节序形式表示,整数以小字节序表示
整数值的精度限制
- 可以精确表示从-2^53 到 2^53(−9007199254740992 到 9007199254740992)的整数
- 2^53 和 2^54 之间的整数= 18014398509481984,取整为 2 的倍数(偶数)
- 2^54 和 2^55 之间的整数= 36028797018963968 舍入为 4 的倍数
内部表示
| 类型 | 标志 | 指数 | 有效域 | 总位数 | 指数偏差 | 位精度 | 小数位数 |
|---|---|---|---|---|---|---|---|
| 16(IEEE 754-2008) | 1 个 | 5 | 10 | 16 | 15 | 11 | 〜3.3 |
| 32 | 1 个 | 8 | 23 | 32 | 127 | 24 | 〜7.2 |
| 64 | 1 个 | 11 | 52 | 64 | 1023 | 53 | 〜15.9 |
| x86 | 1 个 | 15 | 64 | 80 | 16383 | 64 | 〜19.2 |
| 128 | 1 个 | 15 | 112 | 128 | 16383 | 113 | 〜34.0 |
JavaScript 数表示
JavaScript 中采用 IEEE754 64 位浮点数标准,1 位表示标志位,11 位指数位,52 位有效域(有效数字 53 位,包含一位隐含位)
进制转换
二进制转换
整数
整数除余法
8 / 2 = 4 余 0 4 / 2 = 2 余 0 2 / 2 = 1 余 0
十进制 8 转换为二进制为 1000
小数
长乘法
0.1 _ 2 = 0.2 --- 0 0.2 _ 2 = 0.4 --- 0 0.4 _ 2 = 0.8 --- 0 0.8 _ 2 = 1.6 --- 1 0.6 _ 2 = 1.2 --- 1 0.2 _ 2 = 0.4 --- 0
依次类推
十六进制转换
二进制 -> 十六进制 2 ^ 4 = 16
3A(16) = 00111010(2) E7(16) = 11100111(2)
八进制转换
二进制 -> 八进制 2 ^ 3 = 8
65(8) = 110101(2) 17(8) = 001111(2)
计算机编码方式
机器数和真值
带符号位的机器数对应的真正数值称为机器数的真值
机器存储一个具体数字的编码方式
原码
符号位加上真值的绝对值,即用第一位表示符号,其余位表示值
反码
正数的反码是其本身,负数的反码是在其原码的基础上,符号位不变,其余各个位取反
减法 存在两个编码问题
补码
解决了两个编码问题[+0] [-0] 扩充了负数的最小值,以8位二进制为例[10000000, 01111111] = [-128, 127]
反码 + 1
负数二进制可以用补码表示
- 补码具有两种表示形式:0:00000000(+0)和 11111111(-0)
二进制十进制(+1)
txt
11111110 -1
+ 00000010 +2
────────────
100000000 0 ← 不是正确的答案
1 +1 ← 加进位
────────────
00000001 1 ← 正确答案 11111110 -1
+ 00000010 +2
────────────
100000000 0 ← 不是正确的答案
1 +1 ← 加进位
────────────
00000001 1 ← 正确答案- 二进制正数转换负数 正数的二进制取反+1
e.q +2 = 00000010 = 取反 11111101 + 1 = 11111110(-2 的补码形式)
0.6 + 0.3 != 0.9
例子:说明浮点数相加之后的偏差原因
双精度浮点数,1位符号位,11位指数位,52位尾数
0.6 的二进制
0.6 * 2 = 1.2 --- 1 0.2 * 2 = 0.4 --- 0 0.4 * 2 = 0.8 --- 0 0.8 * 2 = 1.6 --- 1 依次类推
得到结果 0.6(10) = 0.1001 1001 1001(2) 指数表示法 0.6(10) = 1.001 1001 1001(2) * 2^-1
0.3 的二进制
0.3 * 2 = 0.6 --- 0 0.6 * 2 = 1.2 --- 1 0.6 * 2 = 1.2 --- 1 0.2 * 2 = 0.4 --- 0 0.4 * 2 = 0.8 --- 0 0.8 * 2 = 1.6 --- 1 以此类推
得到结果 0.3(10) = 0.011001(2) 指数对齐,右移一位 0.1001 1001 * 2^-1
指数对齐相加
0.6 + 0.3
1.0011 001... 0.1001 100... 1.1100 101...
0.11100 101 1 * 2^-1 + 1 * 2^-2 + ... + x^-52 得到近似结果 0.8999999999999999
解决方法
- toFixed
- toPrecision
- 三方库
- math.js
- decimal.js
- big.js