最近在学习《深入理解计算机系统》这本书,欲对其中的一些知识做一点总结。
在理解各种编码之前,我们应该首先明确我们为什么会使用这些东西?
使用目地
为了正确表示二进制下负数。
即用一个正二进制数表示一个负二进制数(即一个映射)。
如何实现|简要解释
在这里简单的解释一下,下下一个标题会较深入解释 :)
设一负数为 X,设 n 为 |X| 的二进制位数。接下来为 X 找一个对应的正数。
原码:对 |X| 加上一个最高位 1 代表符号位,表示 X 为一负数。
移码:对 X 加上一个常数 2^(n-1),把 X 本身转换为一个正数,再以正数编码。
反码:对 X 取 2^n-1 的模(按位取反,方便运算),用模的结果(一个正数)表示 X 。
补码:对 X 取 2^n 的模(即按位取反再加 1 ),用模的结果(一个正数)表示 X 。
为何如此
原码:
没什么好解释的,加上一个最高位来表示此数为负数。
移码:
也没什么好解释的,加上一个被称为偏置常数( bias )的数 2^(n-1),使负数 X 本身变为正数。
反码:
实际上机器是对 |X| 按位取反,所以机器做此操作还是相当快的。
用数学语言表达就是 X 取 2^n-1 的模。
即用一个全部是1的n-1位的二进制数 减去 |X| ,得到 X 的反码表示。
所以 X 的反码加 |X| 就是一个全部为1的n-1位二进制数。
例:
[-5] = ( 2^4-1 ) - | 0101 | = 1010
[-7] = ( 2^4-1 ) - | 0111 | = 1000
补码:
补码这样做的原因是二进制的加减可直接运算,运算的结果和真值的运算结果相同。
机器对 |X| 按位取反然后加 1。
数学表达为 X 对 2^n 取模。
即用 2^n 减去 |X| ,得到 X 的补码表示。
所以 X 的补码加 |X| 就是一个 2^n 二进制数,由于最高位被计算机截断,结果为 0。
例:
[-5] = 2^4 - |0101| = 1011
[-7] = 2^4 - |0111| = 1001
真值和编码之间的转换
除移码外的编码,最高位都可表示此数的正负情况。(即 0正1负)
移码较为简单,故不列出。
原码:
由一个数符位和数值部分组成。
数学公式如下
真值转为编码 | 编码转为真值 | |
---|---|---|
正数 | 直接转换 | 直接转换 |
负数 | 绝对值转换后,设最高位为1 | 数值部分直接转换,添上负号 |
注意编码转为真值时,先按最高位判断正负。
反码:
数学公式如下
真值转为编码 | 编码转为真值 | |
---|---|---|
正数 | 直接转换 | 直接转换 |
负数 | 绝对值按位取反 | 按位取反再转换,添上负号 |
注意编码转为真值时,先按最高位判断正负。
补码:
在补码的转换中,我们可以按照公式求真值,也可以通过一些简单操作进行转换。
真值转为编码 | 编码转为真值 | |
---|---|---|
正数 | 直接转换 | 直接转换 |
负数 | 先转换为正数的补码,再从右向左,第一个1之前的个位取反,变成负的补码 | 从右向左,第一个1之前的个位取反,变成正数的补码,再转换成真值 |
注意编码转为真值时,先按最高位判断正负。
> 18-2-25 更新:重新做了一下排版