补码与带符号整数运算
定义
设有 位二进制容器,整数 的取值范围是 。 的补码编码规定为: 时与 的无符号二进制相同; 时取 的 位二进制。因为 ,负数的编码相当于从 中减去它的绝对值。
补码也可以按位权读:最高位的权是 ,其余位的权仍是正的 ,即
这解释了为什么最高位为1就代表负数,也说明最高位的权不是 而是 ,这是按位读补码时最容易出错的地方。非负数的补码与无符号编码完全一致;同一串位按哪种规则解释,取决于变量的类型,而不是位串本身。
| 位宽 | 表示范围 | 编码个数 |
|---|---|---|
| 8位 | ||
| 16位 | ||
| 32位 |
范围在负数一侧多一个数: 有编码,而 没有。8位中1000 0000是 ,1111 1111是 ,0000 0000是0。无符号整数的位权与加法规则见二进制四则运算。
性质
为什么用补码
原码把最高位当符号位、其余位当绝对值。它有两个问题:0有 +0与 -0两种编码,浪费一个编码;做减法要先比较绝对值大小、再决定符号,电路无法与加法共用。
补码把这套判断省掉:0只有一种编码,且 ,减法化成加法,只需要一个加法器。代价是表示范围不对称,负数比正数多一个,因为原码里 -0占的位置被 占用。
求补码
-
确定位宽:按题目给定的位数,或按变量类型取8、16、32位。
-
正数直接写:最高位为0,其余位与无符号二进制相同。
-
负数取反加一:先写对应正数的 位编码,按位取反,再在末位加1。
位数不足时在左侧补0再取反,取反的结果必须仍是 位;加1产生的进位若超出 位则丢弃。
补码减法
按 计算:把 的 位补码取反加一得到 ,再与 相加。结果超出 位的最高进位被丢弃,这一步不是错误,而是模 运算的自然结果。
溢出判断
补码加法只有同号相加才可能溢出:两个正数相加得到负数,或两个负数相加得到正数。异号相加的结果一定落在表示范围内,不会溢出。
证明
设 且 ,把 写成 位二进制 ,记按位取反的结果为 。
每一位取反后1与0互换,等价于用全1位串 减去 ,所以
再加1,得
右边正是负数 的补码定义,因此取反加一得到的确实是 的编码。加1若产生超出第 位的进位,舍弃它不影响低 位的值,而补码本来就只保留 位。
例子
求 的8位补码
-
写出正数编码:。
-
按位取反:
1111 1010。 -
末位加1:
1111 1011。
所以 在8位补码中存为1111 1011。按最高位权 回代检验:
用快速法求 的8位补码
,从右往左第一个1在权为 的那一位。
-
保留第一个1及其右边:低三位
100不变。 -
左边全部取反:
0001 0取反得1110 1。 -
拼接:得到
1110 1100。
结果与取反加一一致。1110 1100按无符号读是236,正好等于 ,这也印证了负数编码是 。
用8位补码计算
把减法化成加法:。
-
写出 的补码:
0000 0101。 -
求 的补码:,取反得
1111 1100,加1得1111 1101。
把两个编码相加:
两个编码按无符号相加得 。最高位的进位落在第9位,超出8位容器,被丢弃;剩下0000 0010是2,与 一致。
练习
的8位补码是 (只填0和1,不写空格)。
参考解答
,取反得
1111 1010,加1得1111 1011。8位补码能表示的整数范围是:
参考解答
范围是 ,8位即 。负数多出的那一个编码是
1000 0000。用8位补码计算 ,结果的十进制值是 。
参考解答
的补码是
0000 0011, 的补码是1111 1011。相加得1111 1110,按补码读是 。下列8位补码加法中,会溢出的是:
参考解答
与 都超出 ; 同样越界。 在范围内,不溢出。
的8位补码是 (只填0和1,不写空格)。
参考解答
用快速法:,保留第一个1及其右边的
100,左边0001 0取反得1110 1,拼成1110 1100。
交互探索
同一组位,为什么会有两个值?
切换八个二进制位,对照无符号整数与八位补码的解释。
正在准备演示…