补码的计算及存在意义

     在计算机中,数据有三种形式:原码、反码和补码,要弄清楚补码的计算方法,首先让我们来了解三种形式的定义。

1、原码

      如果机器字长为n,那么一个数的原码就是用一个n位的二进制数,其中最高位为符号位:正数为0,负数为1。剩下的n-1位表示该数的绝对值(此处假设机器长度为8)

例如:

X=+7 , [X]原= 0000 0111

X=-7 , [X]原= 1000 0111

位数不够的用0补全。

PS:正数的原、反、补码都一样,0的原码跟反码都有两个,因为这里0被分为+0-0

2、反码

反码就是在原码的基础上,符号位不变其他位按位取反(就是0110)就可以了

例如:

X=-7 , [X]原= 1000 0111 ,[X]反=1111 1000

 

3、补码

补码也非常的简单,就是在反码的基础上按照正常的加法运算加1

例如:

X=-7 , [X]原= 1000 0111 ,[X]反=1111 1000,[X]补=11111001

PS0的补码是唯一的,如果机器字长为8那么[0]=0000 0000

 

在计算补码的时候,楼主一般这么记忆:

正数的原码、反码和补码是一个;

负数补码的计算方法:负数的绝对值对应的二进制数进行取反加一即可。

 

从前面的三种码型的定义,我们可以看出数据的原码,使用符号位来区分了正负数,更加符合人脑直观识别并且用于计算的表达方式。但是在计算机中,通过补码的形式保存数据,这是为什么了?下面我们进行探讨一下。  

在我们的计算中,使用最基础的运算就是加减乘除了,因此最好设计得尽量简单,计算机辨别"符号位"会让计算机的基础电路设计变得复杂,于是,人们想出了将符号位也参与运算的方法。

我们知道,根据运算法则,减去一个正数等于加上一个负数,即:1-1 = 1 + (-1)所以机器可以只有加法而没有减法,这样计算机运算的设计就更简单了。

但是,用原码计算时有一些问题...

于是人们就开始探索将符号位参与运算并且只保留加法的方法。

首先来看原码:

1 - 1 = 1 + (-1) =[0000_0001]原 + [1000_0001]原 = [1000_0010]原 = -2

如果用原码表示, 让符号位也参与计算,显然对于减法来说结果是不正确的。

这也就是为何计算机内部不使用原码表示一个数。

于是,反码出现了,但还有问题...

为了解决原码做减法的问题,出现了反码:

1 - 1 = 1 + (-1) =[0000_0001]原 + [1000_0001]原= [0000_0001]反 + [1111_1110]反 = [1111_1111]反

= [1000_0000]原 = -0

发现用反码计算减法,结果的真值部分是正确的,而唯一的问题其实就出现在"0"这个特殊的数值上。虽然人们理解上+0-0是一样的,但是0带符号是没有任何意义的,而且会有[0000_0000][1000_0000]两个编码表示0


补码解决了遗留的这个问题..

于是补码出现了,它解决了0的符号以及两个编码的问题:

1-1 = 1 + (-1) =[0000_0001]原 + [1000_0001]原 = [0000_0001]补 + [1111_1111]补 = [0000_0000]补

=[0000_0000]原 = 0

这样0[0000_0000]表示,而以前出现问题的-0则不存在了。


除此之外,还可以用 [1000_0000] 表示-128

(-1) + (-127) =[1000_0001]原 + [1111_1111]原 = [1111_1111]补 + [1000_0001]补 = [1000_0000]补

-1-127的结果应该是-128,在用补码运算的结果中, [1000_0000] 就代表-128

注意,-128并没有原码和反码表示。



使用补码不仅仅修复了0的符号以及存在两个编码的问题,而且还能够多表示一个最低数,这就是为什么8位二进制使用原码或反码表示的范围为 [-127, +127],而使用补码表示的范围为 [-128, 127] 的原因。

因为机器使用补码,所以对于编程中常用到的32int类型可以表示范围是  [-2^31,2^31-1] ,因为第一位表示的是符号位,而使用补码表示时又可以多保存一个最小值。

你可能感兴趣的:(c语言)