一、复习10进制转2进制

1)整数部分:除2取余,逆序
2)小数部分:乘2取整,正序
在线工具

二、了解IEEE 754双精度浮点数规范

1) 通过2进制的科学计数法存储。

和10进制的科学计数法类似,二进制的科学技术法格式为1.xxx*2^N。其中需要留意下二进制科学计数法的整数部分都是1,所以在存储时省略整数部分1。

2) 格式:符号位+指数位+尾数位

  1. 符号位S:第 1 位是正负数符号位(sign),0代表正数,1代表负数
  2. 指数位E:中间的 11 位存储指数(exponent),用来表示次方数
    科学计数法中指数E是可以为负数的,在表示负的指数时IEEE754标准引入了一个偏移量1023,在存储指数时加上该偏移量把负数E转成正数。这就导致11位的指数能够表示指数的范围是[-1023, 1024]。
  3. 尾数位M:最后的 52 位是尾数(mantissa),超出的部分自动进一舍零,没有填满的部分自动补0
    如10进制数400.12,用10进制科学计数法表示为:4.0012*10^2,。其中"0012"就是尾数部分。

最终可表示为(图片来源):
clipboard.png

其中S,E,M都是实际存储科学计数法的值。
如10进制4.5转成2进制为:

// Step1 转成二进制
100.1
// Step2 转成二进制科学计数
1.001*2^2
S = 0
E = 2 + 1023 = 2015
M = 001 // 整数1被省略了

形象的查看存储情况,可参考这里

3) 有限集合

IEEE754能表示的实数数量是有限的,假设MAX_VALUE,MIN_VALUE分别表示其表示的最大正数和最小正数,那有限集合可表示为:

[-MAX_VALUE, -MIN_VALUE] U [MIN_VALUE, -MAX_VALUE]

几个有趣的问题

1) 0.1 + 0.2 !== 0.3

0.1,0.2和0.3在转成二进制时都是无限循环的,在存储时会失去精度,0.1+0.2在运算时也会失去精度,导致结果不等于0.3。

2) 给一个数字加上一个非0的增量还等于本身这个数字

1 + Number.MIN_VALUE/2 === 1

这个增量如果小于JS能表示的最小浮点数就会视为0,加上这样的数等于加上0。

3) JS最大整数为啥是2^53-1而不是2^52-1

尾数占用52个bit,再加速省略的那个bit(见2.1)正好53个bit。

4)JS可以精确的表示哪些小数呢

小数部分是这种格式的都可以精确表示。

1/Math.pow(2, N), 其中N是(0, 1024)区间的整数。

如分数1/2,1/4, 1/8。

参考

  1. 抓住数据的小尾巴 - JS浮点数陷阱及解法
  2. 该死的IEEE-754浮点数,说「约」就「约」,你的底线呢?以JS的名义来好好查查你
  3. IEEE 754 计算器
  4. IEEE 754 二进制表示

普拉斯强
2.7k 声望53 粉丝

Coder


« 上一篇
JS-Array