> For the complete documentation index, see [llms.txt](https://wtifs.gitbook.io/diva-notes/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://wtifs.gitbook.io/diva-notes/data-structure/fu-dian.md).

# 浮点

为什么计算机中计算小数时可能产生误差？

计算机中的小数是通过二进制科学计数法表示的，通过尾数\*2^指数表示，当尾数过长时会被截断，截断后就会产生误差。

像十进制0.1这样的，无法通过2的负数次方表示出来，只能截断表示近似数，就会出现误差。

### 什么是浮点数？

浮点数是采用科学计数法的方式来表示的，例如十进制小数 8.345，用科学计数法表示，可以有多种方式：

```
8.345 = 8.345 * 10^0
8.345 = 83.45 * 10^-1
8.345 = 834.5 * 10^-2
...
```

小数点的位置就变得「漂浮不定」了，这就是相对于定点数，浮点数名字的由来。

使用同样的规则，对于二进制数，我们也可以用科学计数法表示，也就是说把基数 10 换成 2 即可。

### 浮点数如何表示数字？

```
V = (-1)^S * M * 2^E
```

S：符号位，取值 0 或 1，决定一个数字的符号，0 表示正，1 表示负

M：尾数，用小数表示，例如前面所看到的 8.345 \* 10^0，8.345 就是尾数

E：指数，用整数表示，例如前面看到的 10^-1，-1 即是指数

将十进制数 25.125 转换为浮点数，转换过程就是这样的（D代表十进制，B代表二进制）：

1. 整数部分：25(D) = 11001(B)
2. 小数部分：0.125(D) = 0.001(B)
3. 用二进制科学计数法表示：25.125(D) = 11001.001(B) = 1.1001001 \* 2^4(B)

所以符号位 S = 0，尾数 M = 1.001001(B)，指数 E = 4(D) = 100(B)

## 浮点数标准

1985年，IEEE 组织推出了浮点数标准，就是我们经常听到的 **IEEE754 浮点数标准**，这个标准统一了浮点数的表示形式，并提供了 2 种浮点格式：

* 单精度浮点数 float：32 位，符号位 S 占 1 bit，指数 E 占 8 bit，尾数 M 占 23 bit
* 双精度浮点数 float：64 位，符号位 S 占 1 bit，指数 E 占 11 bit，尾数 M 占 52 bit

为了使其表示的数字范围、精度最大化，浮点数标准还对指数和尾数进行了规定：

1. 尾数 M 的第一位总是 1（因为 1 <= M < 2），因此这个 1 可以省略不写，它是个**隐藏位**，这样单精度 23 位尾数可以表示了 24 位有效数字，双精度 52 位尾数可以表示 53 位有效数字
2. 指数 E 是个无符号整数，表示 float 时，一共占 8 bit，所以它的取值范围为 0 \~ 255。但因为指数可以是负的，所以规定在存入 E 时在它原本的值加上一个**中间数** 127，这样 E 的取值范围为 -127 \~ 128。表示 double 时，一共占 11 bit，存入 E 时加上中间数 1023，这样取值范围为 -1023 \~ 1024。

## 参考

作者：Kaito 链接：<https://zhuanlan.zhihu.com/p/339949186> 来源：知乎
