位与位运算
位
众所周知,在常见的计算机结构中,数据均以二进制形式存储,单个 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表示负数 - 正数的补码与其二进制原码相同,例如
22为00010110 - 负数的补码 = 将对应正数各位取反后再加 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设计一台计算机》,也可以学习微电子。
形如加法的运算可以使用位运算模拟。你可以尝试完成四则运算的另一种计算方法。