This commit is contained in:
许大仙 2024-08-18 09:54:10 +08:00
parent 054fe08da9
commit 160c07b044
32 changed files with 99 additions and 50 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.5 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 161 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 172 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 156 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 188 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 211 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 253 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 317 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 253 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 380 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 253 KiB

After

Width:  |  Height:  |  Size: 398 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 380 KiB

After

Width:  |  Height:  |  Size: 507 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 398 KiB

After

Width:  |  Height:  |  Size: 534 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 507 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 534 KiB

View File

@ -986,7 +986,7 @@ int main() {
* 在计算机中,数据是从右往左的方式排列的;其中,最右边的是低位,最左边的是高位,即:
![](./assets/20.png)
![](./assets/20.svg)
### 3.4.2 二进制和十进制的转换
@ -1003,13 +1003,13 @@ int main() {
* 示例:十进制转十进制
![](./assets/21.png)
![](./assets/21.svg)
* 示例:二进制转十进制
![](./assets/22.png)
![](./assets/22.svg)
#### 3.4.2.2 十进制转换二进制
@ -1025,35 +1025,35 @@ int main() {
* 示例:十进制转十进制
![](./assets/23.png)
![](./assets/23.svg)
* 示例:十进制转二进制
![](./assets/24.png)
![](./assets/24.svg)
### 3.4.3 二进制转八进制
* 规则:每 3 位二进制就是一个八进制。
* 规则:从右向左,每 3 位二进制就是一个八进制,不足补 0分组转换法
* 示例011 101 001 -> 351
![](./assets/25.png)
![](./assets/25.svg)
### 3.4.4 二进制转十六进制
* 规则:每 4 位二进制就是一个十六进制。
* 规则:从右向左,每 4 位二进制就是一个十六进制,不足补 0分组转换法
* 示例1110 1001 -> 0xE9
![](./assets/26.png)
![](./assets/26.svg)
## 3.5 原码、反码和补码
@ -1061,11 +1061,19 @@ int main() {
* 机器数一个数在计算机的存储形式是二进制我们称这些二进制数为机器数。机器数可以是有符号的用机器数的最高位来存放符号位0 表示正数1 表示负数。
![](./assets/27.png)
> [!IMPORTANT]
>
> 这里讨论的适用于`符号位`的整数int 等;而不适用于`无符号位`的整数unsinged int 等。
* 真值:因为机器数带有符号位,所以机器数的形式值不等于其真实表示的值(真值),以机器数 1000 0001 为例,其真正表示的值(首位是符号位)为 -1而形式值却是 129 ,因此将带有符号位的机器数的真正表示的值称为机器数的真值。
![](./assets/27.svg)
![](./assets/28.png)
* 真值(数据位):因为机器数带有符号位,所以机器数的形式值不等于其真实表示的值(真值),以机器数 1000 0001 为例,其真正表示的值(首位是符号位)为 -1而形式值却是 129 ,因此将带有符号位的机器数的真正表示的值称为机器数的真值。
> [!IMPORTANT]
>
> 这里讨论的适用于`符号位`的整数int 等;而不适用于`无符号位`的整数unsinged int 等。
![](./assets/28.svg)
### 3.5.2 原码
@ -1087,7 +1095,10 @@ int main() {
> [!IMPORTANT]
>
> 按照原码的规则,会出现 `+0``-0` 的情况,即:`0`000 0000+0、`1`000 0000-0显然不符合实际情况所以计算机底层虽然存储和计算的都是二进数但显然不是原码。
> 总结:
>
> * ① 按照原码的规则,会出现 `+0``-0` 的情况,即:`0`000 0000+0、`1`000 0000-0显然不符合实际情况。
> * ② 所以,计算机底层虽然存储和计算的都是二进数,但显然不是原码。
### 3.5.3 反码
@ -1110,7 +1121,10 @@ int main() {
> [!IMPORTANT]
>
> 按照反码的规则,如果是 `+0`,对应的原码是 `0`000 0000那么其反码还是 `0`000 0000 ;如果是 `-0`,对应的原码是 `1`000 0000其反码是 `1`111 1111显然不符合实际情况所以计算机底层虽然存储和计算的都是二进数但显然不是反码。
> 总结:
>
> * ① 按照反码的规则,如果是 `+0`,对应的原码是 `0`000 0000那么其反码还是 `0`000 0000 ;如果是 `-0`,对应的原码是 `1`000 0000其反码是 `1`111 1111显然不符合实际情况。
> * ② 所以,计算机底层虽然存储和计算的都是二进数,但显然不是反码。
### 3.5.4 补码
@ -1130,16 +1144,18 @@ int main() {
| -------- | ------------------- | ------------------- | ------------------- |
| -1 | `1`000 0001 | `1`111 1110 | `1`111 1111 |
* 如果 0 ,按照 `+0` 的情况进行处理,即
* 如果 `0` ,按照 `+0` 的情况进行处理,如下所示
![](./assets/29.png)
![](./assets/29.svg)
* 如果 0 ,按照 `-0` 的情况进行处理,即
* 如果 `0` ,按照 `-0` 的情况进行处理,如下所示
![](./assets/30.png)
![](./assets/30.svg)
> [!IMPORTANT]
>
> 总结:
>
> * ① 补码表示法解决了`原码`和`反码`存在的`两种`零(`+0` 和 `-0`)的问题,即:在补码表示法中,只有`一个`零,即 `0000 0000`
> * ②补码使得`加法运算`和`减法运算`可以统一处理,通过将减法运算`转换`为加法运算,可以简化硬件设计,提高了运算效率。
> * ③ 计算机底层`存储`和`计算`的都是`二进数的补码`。换言之,当读取整数的时候,需要采用逆向的转换,即:将补码转换为原码。正数的原码、反码、补码都是一样的,三码合一。负数的补码转换为原码的方法就是先减去 `1` ,得到反码,再按位取反,得到原码。
@ -1152,23 +1168,12 @@ int main() {
## 3.6 计算机底层为什么使用补码?
* 如果计算是 `2 - 2` ,那么可以转换为 `2 + (-2)`,这样计算机内部在处理`减法计算`的时候,就会将其转换为`加法计算`的形式,以简化硬件设计和提高计算效率。
* `加法`和`减法`是计算机中最基本的运算,计算机时时刻刻都离不开它们,所以它们由硬件直接支持。为了提高加法和减法的运行效率,硬件电路必须设计得尽量简单。
* 对于有符号位的数字来说,内存需要区分符号位和数值位:对于人类来说,很容易识别(最高位是 0 还是 1但是对于计算机来说需要设计专门的电路这无疑增加了硬件的复杂性增加了计算时间。如果能将符号位和数值位等同起来让它们一起参与运算不再加以区分这样硬件电路就可以变得非常简单。
* 此外,加法和减法也可以合并为一种运算,即:加法运算。换言之,减去一个数就相当于加上这个数的相反数,如:`5 - 3` 相当于 `5 +-3``10 --9`相当于 `10 + 9`
> [!NOTE]
>
> * ① 加法和减法是计算机中最基本的运算,计算机时时刻刻都离不开它们,所以它们由硬件直接支持。为了提高加法和减法的运行效率,硬件电路必须设计得尽量简单。
> * ② 对于有符号位的数字来说,内存需要区分符号位和数值位:对于人类来说,很容易识别(最高位是 0 还是 1但是对于计算机来说需要设计专门的电路这无疑增加了硬件的复杂性增加了计算时间。如果能将符号位和数值位等同起来让它们一起参与运算不再加以区分这样硬件电路就可以变得非常简单。
> * ③ 此外加法和减法也可以合并为一种运算加法运算。换言之减去一个数就相当于加上这个数的相反数5 - 3 相当于 5 +-310 --9相当于 10 + 9 。
> * ④ 如果能够实现上述的两个目标,那么只需要设计一种简单的、不用区分符号位和数值位的加法电路,就能同时实现加法运算和减法运算,而且非常高效。其实,这两个目标已经实现了,真正的计算机的硬件电路就是这样设计的。
> * ⑤ 但是,简化硬件电路是有代价的,这个代价就是有符号数在存储和读取的时候都要继续转换。这也是对于有符号数的运算来说,计算机底层为什么使用`补码`的原因所在。
* `最高位`表示`符号位`,由于符号位的存在,如果使用`原码`来计算,就会导致`计算结果不正确`,即:
![](./assets/31.png)
* `补码`的设计可以巧妙的让`符号位`也参与计算,并且可以得到`正确的计算结果`,即:
![](./assets/32.png)
* 如果能够实现上述的两个目标,那么只需要设计一种简单的、不用区分符号位和数值位的加法电路,就能同时实现加法运算和减法运算,而且非常高效。其实,这两个目标已经实现了,真正的计算机的硬件电路就是这样设计的。
* 但是,简化硬件电路是有代价的,这个代价就是有符号数在存储和读取的时候都要继续转换。这也是对于有符号数的运算来说,计算机底层为什么使用`补码`的原因所在。
## 3.7 补码到底是如何简化硬件电路的?
@ -1178,7 +1183,7 @@ int main() {
>
> 直接使用原码表示整数,让符号位也参与运算,那么对于减法来说,结果显然是不正确的。
![](./assets/33.svg)
![](./assets/31.svg)
* 于是,人们开始继续探索,不断试错,终于设计出了`反码`,如下所示:
@ -1186,7 +1191,7 @@ int main() {
>
> 直接使用反码表示整数,让符号位也参与运算,对于 6 +-18来说结果貌似正确。
![](./assets/34.svg)
![](./assets/32.svg)
* 如果我们将`被减数`和`减数`对调一下,即:计算 `18 - 6` 的结果,也就是 `18 +-6`的结果,继续采用`反码`来进行运算,如下所示:
@ -1195,15 +1200,15 @@ int main() {
> * ① 6 - 186+-18如果采用`反码`计算结果是正确的但是18 - 618 +-6如果采用`反码`计算,结果相差 1 。
> * ② 可以推断:如果按照`反码`来计算,小数 - 大数,结果正确;而大数 - 小数,结果相差 1 。
![](./assets/35.svg)
![](./assets/33.svg)
* 对于这个相差的 `1` 必须进行纠正,但是又不能影响`小数-大数`的结果。于是,人们又绞尽脑汁设计出了`补码`,给`反码`打了一个`“补丁”`,终于把相差的 `1` 给纠正过来了。那么,`6 - 18` 按照`补码`的运算过程,如下所示:
![](./assets/36.svg)
![](./assets/34.svg)
* 那么,`18 - 6` 按照`补码`的运算过程,如下所示:
![](./assets/37.svg)
![](./assets/35.svg)
> [!IMPORTANT]
>