跳转至

第 2 章:位,数据类型,操作

数据类型

位,字节

一个位(Bit)表示 0 或者 1。一个字节(Byte)由 8 个位组成。它们撑起了计算机表示数据的基础。

比如在电路中,最高电压是 2.9 V,那么让 [0 V, 0.5 V] 表示 0,[2.4 V, 2.9 V] 表示 1 是常有的事(也可以反过来)。

根据需要,我们可以区分这些数据类型:

  • 无符号整数
  • 有符号整数
  • 逻辑变量
  • 浮点数
  • ASCII

原码,反码和补码

怎么优雅地表示有符号整数呢?先拿最高位作为符号位吧。0 就是非负数,1 就是负数。

反码 1's Complement

负数的二进制码由它绝对值的二进制码全部取反组成。比如在 4 位情况下,6 = 0110b,-6 = 1001b;一共可以表示 [-7, 7] 的整数。

有什么问题?0 该怎么表示?0000b 还是 1111b?这就是问题:正负 0 的问题。

补码 2's Complement

为了解决上面这个问题,补码出现了。可以通过 0 - 某个数得到它的补码。(怎么感觉比上面那个还明显一些?)

另一种方式是,一个负数的补码就是把它的绝对值对应的二进制表示全部取反后加个 1。

比如 4 位的 -8 的补码:8 = 1000b;取反:b0111;加 1:1000b。

哇哦,-8 的补码和它自己相同!怎么回事呢?因为这里的加法就是在模 16 意义下进行的,对一个数 -8 和 +8 效果是一样的。

IEEE 下的浮点数

比如拿 32 位下的情况:

符号位 Sign 指数部分 Exponent 分数部分 Fraction
S = [31],1 位 e = [30:23],k = 8 位 f = [22:0],n = 23 位

它们表示的值就是 \((-1)^S \times 2^E \times F\)。注意 E 和 F 和上面的 e 和 f 并不相等!

规约形式(一般情况)

是 e 不都是 0 且不都是 1 的情况。这个时候 e 的范围是 \([1, 2^k - 2]\)

给它一个偏移 bias = \(2^{k-1} - 1\),那么 E = e - bias,范围是 \([-2^{k-1} + 2, 2^{k-1} + 1]\)

对于 F,它等于 \(1.f_{n-1} f_{n-2} \cdots f_0\)

非规约形式

e 全是 0。这个时候 E = 1 - bias = \(-2^{k-1} +2\)(上面的 E 的最小值),而 F 等于 \(0.f_{n-1} f_{n-2} \cdots f_0\)

你也不希望浮点数表示范围的 0 旁边那一块是空的吧?

特殊值

e 全是 1。如果 f 全为 0,那么根据符号位的不同来表示正无穷大或者负无穷大。

如果 f 里面有 1,那就是 NaN 了。

ASCII 码

美国标准交换码(American Standard Code for Information Interchange,ASCII)定义了 8 位的二进制数都是对应了什么符号。比如字符“0”是 0x30,字符“a”是 0x61。

逻辑门

计算机系统 I 上过了。

Patt: TJJ is my TA?

iotang: ??????

为什么 C 里面的 bool 类型长度是 8 位?

因为每个变量都得能被寻址。你怎么单独给一个位寻址?