补码,有符号数在计算机系统中的表示

文章来自微信公众号“科文路”,欢迎关注、互动。转发须注明出处。

怎么用二进制数表示负数呢?

啊,五一结束盼端午~收假前复习个知识点,恢复活力!

计算机中,有符号数通常有三种表示方法,原码反码补码

而补码(two’s complement)是最常见的形式。虽然 C 语言标准没有要求必须用补码表示有符号整数,但几乎所有机器都是这么做的。

原因在于,用补码,可以将符号位和数值域统一处理;同时,加法和减法也可以统一处理。

以下以整数为例。

先看一下,你能写出下面这段代码的输出吗?

1
2
3
4
5
6
7
8
9
#include <stdio.h>

int main()
{
int i = -42;
unsigned int ui = 42;

printf("int(-42): %x, unsigned(42): %x\n", i, ui)
}

===

===

===

输出是

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. 将原码按位取反
  2. 加 1

一个求补码的例子

以 -42 为例,

  1. 原码(这里省略一下),… 0000 0010 1010,按位取反后,… 1111 1101 0101
  2. 加 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,就到这里吧,够消化一阵了~

都看到这儿了,不如关注每日推送的“科文路”、互动起来~

补码,有符号数在计算机系统中的表示

https://xlindo.com/kewenlu2022/posts/524b28d8/

Author

xlindo

Posted on

2022-05-04

Updated on

2023-05-10

Licensed under

Comments