关于补码的解释

今天讲补码的时候卡壳了,有点尴尬,太想当然了,向童鞋们道歉!在这里把补码的原理解释一遍。

先看8位的二进制的范围[00000000, 11111111],我们暂时只考虑真值,即这里面所有的数都表示数值,其对应的十进制数的范围为[0, 255],也就是说8位二进制数的模为256,如果把这个范围分为两部分[00000000, 01111111]和[10000000, 11111111],后面的这一部分是不是刚好可以表示负数的二进制补码呢?

我们看一个具体的例子,如果我们要表示-3,其二进制补码为:

(10000011) = (11111100) = (11111101)

如果只把-3的补码的编码当数值看(没有符号位),则(11111101)2 = 253,那-3和253是什么关系呢?

-3 + 256 = 253,也就是-3 = 253(mod 256)(注:如果这个不能理解,就假设钟表圆盘上有256个刻度,依次标为0,1, …, 255,在任意一个时刻点,钟表顺时针拨253个刻度和逆时针拨3个刻度指向同一个刻度)

这下应该明白了。 从这个角度,也就可以解释5-3=5+(-3)=5+253 (mod 256) = 258 (mod 256) = 2(mod 256),用二进制补码运算时,将符号位能带入计算也是因为这个原因。

回到8位二进制范围[00000000, 11111111],如果用二进制补码表示带符号数,[00000000, 01111111]表示正数,[10000000, 11111111]表示负数,则(10000001) = -127, (10000010)=-126, …, (11111111) = -1,那多出来的(10000000) = ? 显然,根据补码的定义,符号位为1,这应该是负数,从节约资源的角度,将其定义为-128最合适,这也就是为什么8位二进制补码的范围为[-128~127]的原因。

在计算机系统中,数值一律用补码来表示和存储。使用补码,可以将符号位和其它位统一处理;同时,减法也可按加法来处理。另外,两个用补码表示的数相加时,如果最高位(符号位)有进位,则进位被舍弃[^2]。 补码与原码的转换过程几乎是相同的。求给定数值的补码表示分以下两种情况:正数的补码与原码相同;负数的补码是在其原码的基础上,符号位不变,其余各位取反,最后加 1。例如,+3 的补码为 0000 0011,-3 的原码为 1000 0011,取反后为 1111 1100,再加 1 得到补码 1111 1101。计算 +3 - 3 时,可转化为 +3 + (-3) 的补码运算,即 0000 0011 + 1111 1101 = 0000 0000,符合预期结果[^1][^2]。 设一个数 a 的二进制位数为 n 位,其模为 2^(n - 1),而 2^(n - 1) 的二项展开是 1 + 2^0 + 2^1 + 2^2 + …… + 2^(n - 2)。式子 -a = 2^(n - 1) - 2^(n - 1) - a 中,2^(n - 1) - a 代入 a = k0 * 2^0 + k1 * 2^1 + k2 * 2^2 + …… + k(n - 2) * 2^(n - 2) 和 2^(n - 1) = 1 + 2^0 + 2^1 + 2^2 + …… + 2^(n - 2) 两式,可得到 2^(n - 1) - a = (1 - k(n - 2)) * 2^(n - 2) + (1 - k(n - 3)) * 2^(n - 3) + …… + (1 - k2) * 2^2 + (1 - k1) * 2^1 + (1 - k0) * 2^0 + 1,这正是取反再加 1 规则的代数原理所在。因为 k0, k1, k2 等不是 0 就是 1,所以 1 - k0, 1 - k1, 1 - k2 的运算就是二进制下的取反,而加 1 是因为 2^(n - 1) 的二项展开式最后还有一项 1。式子中的 -2^(n - 1) 这项就是补码里首位的 1,首位 1 在转化为十进制时要乘上 2^(n - 1),这正是 n 位二进制的模[^4]。 ### C 语言示例 ```c #include <stdio.h> // 函数:获取一个数的补码表示(简单示例,适用于 8 位整数) void printComplement(int num) { unsigned char complement = (unsigned char)num; for (int i = 7; i >= 0; i--) { printf("%d", (complement >> i) & 1); } printf("\n"); } int main() { int num1 = 3; int num2 = -3; printf("+3 的补码: "); printComplement(num1); printf("-3 的补码: "); printComplement(num2); return 0; } ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值