This commit is contained in:
krahets
2024-04-09 20:43:40 +08:00
parent d8caf02e9e
commit a6adc8e20a
48 changed files with 1599 additions and 571 deletions

View File

@ -36,3 +36,35 @@ comments: true
**Q**:在构建栈(队列)的时候,未指定它的大小,为什么它们是“静态数据结构”呢?
在高级编程语言中我们无须人工指定栈队列的初始容量这个工作由类内部自动完成。例如Java 的 `ArrayList` 的初始容量通常为 10。另外扩容操作也是自动实现的。详见后续的“列表”章节。
**Q**:原码转补码的方法是“先取反后加 1”那么补码转原码应该是逆运算“先减 1 后取反”,而补码转原码也一样可以通过“先取反后加 1”得到这是为什么呢
**A**:这是因为原码和补码的相互转换实际上是计算“补数”的过程。我们先给出补数的定义:假设 $a + b = c$ ,那么我们称 $a$ 是 $b$ 到 $c$ 的补数,反之也称 $b$ 是 $a$ 到 $c$ 的补数。
给定一个 $n = 4$ 位长度的二进制数 $0010$ ,如果将这个数字看作原码(不考虑符号位),那么它的补码需通过“先取反后加 1”得到
$$
0010 \rightarrow 1101 \rightarrow 1110
$$
我们会发现,原码和补码的和是 $0010 + 1110 = 10000$ ,也就是说,补码 $1110$ 是原码 $0010$ 到 $10000$ 的“补数”。**这意味着上述“先取反后加 1”实际上是计算到 $10000$ 的补数的过程**。
那么,补码 $1110$ 到 $10000$ 的“补数”是多少呢?我们依然可以用“先取反后加 1”得到它
$$
1110 \rightarrow 0001 \rightarrow 0010
$$
换句话说,原码和补码互为对方到 $10000$ 的“补数”,因此“原码转补码”和“补码转原码”可以用相同的操作(先取反后加 1 )实现。
当然,我们也可以用逆运算来求补码 $1110$ 的原码,即“先减 1 后取反”:
$$
1110 \rightarrow 1101 \rightarrow 0010
$$
总结来看,“先取反后加 1”和“先减 1 后取反”这两种运算都是在计算到 $10000$ 的补数,它们是等价的。
本质上看,“取反”操作实际上是求到 $1111$ 的补数(因为恒有 `原码 + 反码 = 1111`);而在反码基础上再加 1 得到的补码,就是到 $10000$ 的补数。
上述 $n = 4$ 为例,其可推广至任意位数的二进制数。