补码,有符号数在计算机系统中的表示
文章来自微信公众号“科文路”,欢迎关注、互动。转发须注明出处。
怎么用二进制数表示负数呢?
啊,五一结束盼端午~收假前复习个知识点,恢复活力!
计算机中,有符号数通常有三种表示方法,原码、反码和补码。
而补码(two’s complement)是最常见的形式。虽然 C 语言标准没有要求必须用补码表示有符号整数,但几乎所有机器都是这么做的。
原因在于,用补码,可以将符号位和数值域统一处理;同时,加法和减法也可以统一处理。
以下以整数为例。
先看一下,你能写出下面这段代码的输出吗?
1 |
|
===
===
===
输出是
1 | int(-42): ffffffd6, unsigned(42): 2a |
也就是
- -42,1111 1111 1111 1111 1111 1111 1101 0110
- 42, 0010 1010
42 不难理解,但 -42 为什么是这样?
残存的记忆告诉你,负数不就是最高位是 1 吗?而且这后面这一坨也不像是 42 啊?
这就是补码。
补码的定义
CSAPP, p45
对于向量 $\mathbb{x}=[x_{w-1},x_{w-2},\cdots,x_0]$,
$$
\begin{equation}
\nonumber
\begin{split}
\text{B2T}w(\mathbb{x}) \doteq -x{w-1}2^{w-1} + \sum_{i=0}^{w-2}x_i2^i
\end{split}
\end{equation}
$$
例如,
$$
\begin{equation}
\nonumber
\begin{split}
\text{B2T}_4([0101])=-0\cdot2^3 + 1\cdot2^2 +\ 0\cdot2^1 + 1\cdot2^0=5
\end{split}
\end{equation}
$$
求补码
正数的补码就是其二进制表示。
负数求补码按以下步骤:
- 将原码按位取反
- 加 1
一个求补码的例子
以 -42 为例,
- 原码(这里省略一下),… 0000 0010 1010,按位取反后,… 1111 1101 0101
- 加 1,… 1111 1101 0110
所以 -42 的补码形式是 [… 1111 1101 0110]
哈,和上面程序结果一致。再带到上文 $\text{B2T}_w(\mathbb{x})$ 的公式算一下,
$$
\begin{equation}
\nonumber
\begin{split}
\text{B2T}_12([111111010110])=-1\cdot2^{11} + \ 1\cdot2^{10} + 1\cdot2^9 + 1\cdot2^8 +\ 1\cdot2^7 + 1\cdot2^6 + 0\cdot2^5 +\ 1\cdot2^4 + 0\cdot2^3 + 1\cdot2^2 +\ 1\cdot2^1 + 0\cdot2^0\
= -2048 + 1024 + 512 +\ 256 + 128 + 64 +\ 0 + 16 + 0 + \4 + 2 + 0\
= -42
\end{split}
\end{equation}
$$
Bingo!自洽!
OK,就到这里吧,够消化一阵了~
都看到这儿了,不如关注每日推送的“科文路”、互动起来~
补码,有符号数在计算机系统中的表示