c语言补码的理解(为什么四位中,-8没有原码?)

同余数概念参考该文。

前言:

补码的理解:

1)思路1:将负数变成正数,如钟表,当前时间-1,与+11相同。 补码= 该负数+模

11= -1+12,12为模

原理:11和-1是相较12的同余数。,这样实现了用一个正数替换一个负数。

参考该文。

2)思路2:周期函数的角度来理解,周期函数的性质,f(x)=f(x+T),T为周期。

上例中钟表的例子,12即为周期,当前时间-1 =当前时间-1+12=当前时间+11.

以下示例来源于原码,反码,补码杂谈 - 方戈 - 博客园

  • 计算机中存的是补码。
  • 正数的补码等于其本身;
  • 负数补码的计算方法:负数的补码等于负数加上模(负加模-----因为负数的绝对值与其补码之和等于模);实质是同余数(时钟原理);
  • 对于一个4位的二进制数来说,我们用首位为1的8个数,来表示负数,首位为0的8个数来表示非负数;
  • 4位的二进制数,共能表示2*2*2*2=16个数,故其模为16.

比如:4位运算,,-1的补码是-1+16 = 15;(1111),这种理解方式,其实是没有符号位的概念。。。即:我们用同余数来表示这个负数

4位运算,我们只使用了3位,将高位作为符号位,因此我们将高位是1的8个数,用来表示负数。

  • 之所以-1的补码是1111,-2的补码是1110,是因为 -2  + 1 = -1   (即:1110 +0001 = 1111);

而  0 = -1 + 1;即:(1111 + 0001 = 0000),所以,-0(补码0000 )和+0(0000)合二为0;这样多出来一个编码:1000,他没有原码(没有哪个原码的补码是1000),因为 1000+1 = 1001(-7),所以我们将1000代表为-8的编码;因此,-8是没有原码的(因为1000是没有原码的。)

(六)补码实例

好吧,接下来我们就做一做四位二进制数的减法吧(先不引入符号位)

0110(6)-0010(2)【6-2=4,但是由于计算机中没有减法器,我们没法算】

这个时候,我们想想时钟运算中,减去一个数,是可以等同于加上另外一个正数(同余数)

那么这个数是什么呢?从时钟运算中我们可以看出这个数与减数相加正好等于模。

那么四位二进制数的模是多少呢?也就是说四位二进制数最大容量是多少?其实就是2^4=16=10000B

那么2的同余数,就等于10000-0010=1110(14)

既然如此

0110(6)-0010(2)=0110(6)+1110(14)=10100(20=16+4)

OK,我们看到按照这种算法得出的结果是10100,但是对于四位二进制数,最大只能存放4位(硬件决定了),如果我们低四位,正好是0100(4),正好是我们想要的结果,至于最高位的‘1’,计算机会把他放入psw寄存器进位位中。8位机则会放在cy中,x86会放在cf中(这个我们不作讨论)

这个时候,我们再想想在四位二进制数中,减去2,就相当于加上它的同余数14(至于它们为什么同余,还是建议看《计算机组成原理》)

但是减去2,从另外一个角度来说,也是加上(-2)。即加上(-2)和加上14其实得到的二进制结果除了进位位,结果是一样的。

如果我们把1110(14)的最高位看作符号位后就是(-2)的补码,这可能也是为什么负数的符号位是‘1’而不是‘0’

而且在有符号位的四位二进制数中,能表示的只有‘-8~7’,而无符号位数(14)的作用和有符号数(-2)的作用效果其实是一样的。

那正数的补码呢?加上一个正数,加法器就直接可以实现。所以它的补码就还是它本身。

下图给出带符号位四位二进制的补码表示法 
图片描述

由上图可以看出来,1000是没有原码的,因为1001(-7)+1111(-1) = 1000(-8);所以,我们规定1000为-8.

到这里,我们发现原码,反码的问题,补码基本解决了。

在补码中也不存在负零了,因为1000表示-8

这是因为根据上面的补码图,做减法时,0001(1)+1111(-1)=0000 
我们再也不需要一个1000来表示负0了,就把它规定为-8

负数与负数相加的问题也解决了1111(-1)+1110(-2)=1101(-3)

可能说得有点绕,但是实在是没办法。其实我觉得补码还可以这样画。 
图片描述

很优美有没有,如果你想想地理课本,0不就相当于本初子午线,-8不就是180°,而正数相当于西经,负数相当于东经。

(七)为何这样求补码

然后我们再来看看为什么负数的补码的求法为什么是反码+1

因为负数的反码加上这个负数的绝对值正好等于1111,再加1,就是1000,也就是四位二进数的模

而负数的补码是它的绝对值的同余数,可以通过模减去负数的绝对值,得到他的补码。

所以 负数的补码就是它的反码+1。

有点绕吧,只能说很难算清楚,你们还是自己算算吧。还有上面我提到的另外一种算法。

接下来,我要说一下我自己算补码的小技巧。

看上面那个图。

如果我们把-8当成负数的原点。那么-5的补码是多少呢?

-5=-8+3

-5的补码就是-8的补码加3

1000(-8) +0011(3)=1011(-5)

所以完全可以口算出-5的补码是1011

当然,也可以记住-1的补码是1111口算减法得出(计算机没法算减法,我们可以人为的算减法,就像算十进制减法一样。

对于八位加法器的话,可以把-128当补码原点。十六位可以把-32768当补码原点。

是的,128256(八位二进制数的模)的一半,3276865536(十六位二进数的模)的一半

也很方便有没有,而且简单的是

补码原点总是最高位是‘1’,其他位是‘0’

所以做加法总是简单得可以口算。

总结:

综上,求补码的两种方式:

1)通过负加模思路

如单字节中,-128的补码是-128+256  = 128(0x80);-1的补码是-1+256=255(0xFF).

2)通过最小的负数来求补码

如单字节,-120的补码是 -120 = -128+8 = 0x80+0x08=0x88

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值