位与位运算

众所周知,在常见的计算机结构中,数据均以二进制形式存储,单个 0/1 单元称为位/比特(bit)。为了便于管理,每 8 位组成 1 个字节(byte)。使用前置修饰符,如 K —— 组成 KB 表示 $2^{10}$ 字节等。在硬件中,数据存储可能存在分区、分块等措施,此处不进行赘述。

利用 bitstring 函数,你可以方便地列出某个东西的各位数据

julia> bitstring(31)
"0000000000000000000000000000000000000000000000000000000000011111"

无符号整数

无符号整数的存储方式是最容易理解的:即单纯使用二进制。 以 $22=(10110)_2$ 为例: | 单位数值 | 权值 | 结果 | | :-: | :-: | :-: | | 0 | 1 | 0 | | 1 | 2 | 2 | | 1 | 4 | 4 | | 0 | 8 | 0 | | 1 | 16 | 16 |

带符号整数

带符号整数使用补码(two's complement)来表示负数,这是目前几乎所有计算机都采用的方案。

以 8 位整数为例:

  • 最高位(第 7 位)为符号位0 表示非负,1 表示负数
  • 正数的补码与其二进制原码相同,例如 2200010110
  • 负数的补码 = 将对应正数各位取反后再加 1,例如 -1 的补码为 11111111
julia> bitstring(Int8(22))
"00010110"

julia> bitstring(Int8(-1))
"11111111"

julia> bitstring(Int8(-22))
"11101010"

补码的优点在于加减法可以统一用同一套电路处理,无需区分符号。此外,0 的表示是唯一的(不像原码有 +0-0 之分)。

可参阅此文获取更详细的推导。

浮点数

IEEE 754 标准规定了浮点数在内存中的存储格式。以 64 位 Float64 为例,其位布局为:

部分位数作用
符号位1 位0 为正,1 为负
阶码(指数)11 位存储 2 的指数,有固定偏移量(bias = 1023)
尾数(有效数字)52 位存储有效数字的小数部分

这种格式可以表示极大或极小的数,但也因此存在精度限制——两个看似接近的浮点数在运算后可能累积误差。你将会在浮点数章节读到更多内容。

位运算

在阅读布尔逻辑后,你应该了解了如何对 0/1 值进行布尔运算。而形如“按位与”的位运算,就是对于二进制中的每一位分别进行与运算,得到一个新的二进制数。

杂项

关于硬件上的具体实现,请参阅模拟电路数字电路《从0到1设计一台计算机》,也可以学习微电子。

形如加法的运算可以使用位运算模拟。你可以尝试完成四则运算的另一种计算方法