diff --git a/docs/notes/01_c-basic/02_xdx/assets/33.svg b/docs/notes/01_c-basic/02_xdx/assets/33.svg new file mode 100644 index 0000000..29f26ac --- /dev/null +++ b/docs/notes/01_c-basic/02_xdx/assets/33.svg @@ -0,0 +1,4 @@ + + + +
0
0
0
0
0
0
0
0
原码运算
0
0
0
0
0
1
1
0
6 的原码
6 + (-18)采用原码计算
-18 的原码
1
0
0
0
0
0
0
0
0
0
0
1
0
0
1
0
结果(原码)
1
0
0
0
0
0
0
0
0
0
0
1
1
0
0
0
符号位
数值位(真值)
-24
\ No newline at end of file diff --git a/docs/notes/01_c-basic/02_xdx/assets/34.svg b/docs/notes/01_c-basic/02_xdx/assets/34.svg new file mode 100644 index 0000000..d24337b --- /dev/null +++ b/docs/notes/01_c-basic/02_xdx/assets/34.svg @@ -0,0 +1,4 @@ + + + +
0
0
0
0
0
0
0
0
0
0
0
0
0
1
1
0
6 的原码(反码)
6 + (-18)采用反码计算
-18 的原码
1
0
0
0
0
0
0
0
0
0
0
1
0
0
1
0
结果(反码)
1
1
1
1
1
1
1
1
1
1
1
1
0
0
1
1
符号位
数值位(真值)
-18 的反码
1
1
1
1
1
1
1
1
1
1
1
0
1
1
0
1
1
0
0
0
0
0
0
0
0
0
0
0
1
1
0
0
结果(原码)
反码运算
-12
\ No newline at end of file diff --git a/docs/notes/01_c-basic/02_xdx/assets/35.CocAjZjO-1721011612199-6.png b/docs/notes/01_c-basic/02_xdx/assets/35.CocAjZjO-1721011612199-6.png deleted file mode 100644 index 87fcdaa..0000000 Binary files a/docs/notes/01_c-basic/02_xdx/assets/35.CocAjZjO-1721011612199-6.png and /dev/null differ diff --git a/docs/notes/01_c-basic/02_xdx/assets/35.svg b/docs/notes/01_c-basic/02_xdx/assets/35.svg new file mode 100644 index 0000000..0bbf08a --- /dev/null +++ b/docs/notes/01_c-basic/02_xdx/assets/35.svg @@ -0,0 +1,4 @@ + + + +
0
0
0
0
0
0
0
0
0
0
0
1
0
0
1
0
18 的原码(反码)
18 + (-6)采用反码计算
-6 的原码
1
0
0
0
0
0
0
0
0
0
0
0
0
1
1
0
结果(反码)
0
0
0
0
0
0
0
0
0
0
0
0
1
0
1
1
符号位
数值位(真值)
-6 的反码
1
1
1
1
1
1
1
1
1
1
1
1
1
0
0
1
0
0
0
0
0
0
0
0
0
0
0
0
1
0
1
1
结果(原码)
反码运算
11
1
溢出,丢弃
\ No newline at end of file diff --git a/docs/notes/01_c-basic/02_xdx/assets/36.svg b/docs/notes/01_c-basic/02_xdx/assets/36.svg new file mode 100644 index 0000000..f31c8c0 --- /dev/null +++ b/docs/notes/01_c-basic/02_xdx/assets/36.svg @@ -0,0 +1,4 @@ + + + +
0
0
0
0
0
0
0
0
0
0
0
0
0
1
1
0
6 的原码(反码,补码)
6 + (-18)采用补码计算
-18 的原码
1
0
0
0
0
0
0
0
0
0
0
1
0
0
1
0
结果(补码)
1
1
1
1
1
1
1
1
1
1
1
1
0
1
0
0
符号位
数值位(真值)
-18 的反码
1
1
1
1
1
1
1
1
1
1
1
0
1
1
0
1
1
1
1
1
1
1
1
1
1
1
1
1
0
0
1
1
结果(反码)
补码运算
-12
1
1
1
1
1
1
1
1
1
1
1
0
1
1
1
0
-18 的补码
结果(原码)
1
0
0
0
0
0
0
0
0
0
0
0
1
1
0
0
\ No newline at end of file diff --git a/docs/notes/01_c-basic/02_xdx/assets/37.svg b/docs/notes/01_c-basic/02_xdx/assets/37.svg new file mode 100644 index 0000000..2548443 --- /dev/null +++ b/docs/notes/01_c-basic/02_xdx/assets/37.svg @@ -0,0 +1,4 @@ + + + +
0
0
0
0
0
0
0
0
0
0
0
1
0
0
1
0
18 的原码(反码,补码)
18 + (-6)采用补码计算
-6 的原码
1
0
0
0
0
0
0
0
0
0
0
0
0
1
1
0
结果(补码)
0
0
0
0
0
0
0
0
0
0
0
0
1
1
0
0
符号位
数值位(真值)
-6 的反码
1
1
1
1
1
1
1
1
1
1
1
1
1
0
0
1
0
0
0
0
0
0
0
0
0
0
0
0
1
1
0
0
结果(反码)
补码运算
12
1
溢出,丢弃
1
1
1
1
1
1
1
1
1
1
1
1
1
0
1
0
-6 的补码
结果(原码)
0
0
0
0
0
0
0
0
0
0
0
0
1
1
0
0
\ No newline at end of file diff --git a/docs/notes/01_c-basic/02_xdx/index.md b/docs/notes/01_c-basic/02_xdx/index.md index 7941057..ba88d4f 100644 --- a/docs/notes/01_c-basic/02_xdx/index.md +++ b/docs/notes/01_c-basic/02_xdx/index.md @@ -1140,9 +1140,9 @@ int main() { > [!IMPORTANT] > -> * ① 补码表示法解决了`原码`和`反码`存在的`两种`零(`+0` 和 `-0`)的问题,即:在补码表示法中,只有`一个`零,即 0000 0000。 +> * ① 补码表示法解决了`原码`和`反码`存在的`两种`零(`+0` 和 `-0`)的问题,即:在补码表示法中,只有`一个`零,即 `0000 0000`。 > * ②补码使得`加法运算`和`减法运算`可以统一处理,通过将减法运算`转换`为加法运算,可以简化硬件设计,提高了运算效率。 -> * ③ 计算机底层`存储`和`计算`的都是`二进数的补码`。 +> * ③ 计算机底层`存储`和`计算`的都是`二进数的补码`。换言之,当读取整数的时候,需要采用逆向的转换,即:将补码转换为原码。正数的原码、反码、补码都是一样的,三码合一。负数的补码转换为原码的方法就是先减去 `1` ,得到反码,再按位取反,得到原码。 ### 3.5.5 总结 @@ -1170,3 +1170,47 @@ int main() { ![](./assets/32.png) +## 3.7 补码到底是如何简化硬件电路的? + +* 假设 6 和 18 都是 short 类型,现在我们要计算 `6 - 18` 的结果,根据运算规则,它等价于 `6 +(-18)`。如果按照采用`原码`来计算,那么运算过程是这样的,如下所示: + +> [!NOTE] +> +> 直接使用原码表示整数,让符号位也参与运算,那么对于减法来说,结果显然是不正确的。 + +![](./assets/33.svg) + +* 于是,人们开始继续探索,不断试错,终于设计出了`反码`,如下所示: + +> [!NOTE] +> +> 直接使用反码表示整数,让符号位也参与运算,对于 6 +(-18)来说,结果貌似正确。 + +![](./assets/34.svg) + +* 如果我们将`被减数`和`减数`对调一下,即:计算 `18 - 6` 的结果,也就是 `18 +(-6)`的结果,继续采用`反码`来进行运算,如下所示: + +> [!NOTE] +> +> * ① 6 - 18,即:6+(-18),如果采用`反码`计算,结果是正确的;但是,18 - 6,即:18 +(-6),如果采用`反码`计算,结果相差 1 。 +> * ② 可以推断:如果按照`反码`来计算,小数 - 大数,结果正确;而大数 - 小数,结果相差 1 。 + +![](./assets/35.svg) + +* 对于这个相差的 `1` 必须进行纠正,但是又不能影响`小数-大数`的结果。于是,人们又绞尽脑汁设计出了`补码`,给`反码`打了一个`“补丁”`,终于把相差的 `1` 给纠正过来了。那么,`6 - 18` 按照`补码`的运算过程,如下所示: + +![](./assets/36.svg) + +* 那么,`18 - 6` 按照`补码`的运算过程,如下所示: + +![](./assets/37.svg) + +> [!IMPORTANT] +> +> 总结:采用`补码`的形式正好将相差的 `1`纠正过来,也没有影响到小数减大数,这个“补丁”非常巧妙。 +> +> * ① 小数减去大数,结果为负,之前(负数从反码转换为补码需要 +1)加上的 1 ,后来(负数从补码转换为反码要 -1)还需要减去,正好抵消掉,所以不会受到影响。 +> * ② 大数减去小数,结果为正,之前(负数从反码转换为补码需要 +1)加上的 1 ,后来(正数的补码和反码相同,从补码转换为反码不用 -1)就没有再减去,不能抵消掉,这就相当于给计算结果多加了一个 1。 +> +> `补码`这种天才般的设计,一举达成了之前加法运算和减法运算提到的两个目标,简化了硬件电路。 +