原码反码补码的概念详解及转换方法实例

如果补码的首位是0,那它就表示一个正数,直接把二进制数转换为十进制数就行。
例如:[x]补=00110010,因为(110010)2=50
x的真值就是50。
如果补码的首位是1,那它就表示一个负数,可以先-1算出它的反码,再根据反码写出原码。最后把符号位后面的二进制数转换为十进制数,前面加上“-”就行。
例如:[x]补=10110010,则[x]反=10110001,[x]原=11001110(注意:符号位的1不参与取反不变)
因为(1001110)2=78
x的真值就是-78。

/*****************************************

原码、反码、补码
 
一、什么是原码、反码、补码

原码:将整数,转换成二进制,就是其原码。
如单字节的5的原码为:0000 0101;-5的原码为1000 0101。(最高位为符号位正为0负为1)

反码:正数的反码就是其原码;负数的反码是将原码中,除符号位以外,每一位取反。
如单字节的5的反码为:0000 0101;-5的反码为1111 1010。

补码:正数的补码就是其原码;负数的反码+1就是补码。
如单字节的5的补码为:0000 0101;-5的补码为1111 1011。

二、为什么要有这三类码

计算机只能识别0和1,使用的是二进制。而在日常生活中人们使用的是十进制,并且我们用的数值有正负之分。于是在计算机中就用一个数的最高位存放符号(0为正,1为负)。这就是机器数的原码了。
有了数值的表示方法就可以对数进行算术运算,但是很快就发现用带符号位的原码进行乘除运算时结果正确,而在加减运算的时候就出现了问题,如下:假设字长为8bits
(1) 10 - (1)10 = (1)10 + (-1)10 = (0)10
(0 0000001)原 + (1 0000001)原 = (1 0000010)原 = ( -2 ) 显然不正确。
因为在两个整数的加法运算中是没有问题的,于是就发现问题出现在带符号位的负数身上。对除符号位外的其余各位逐位取反就产生了反码。反码的取值空间和原码相同且一一对应。下面是反码的减法运算:
(1)10 - (1)10 = (1)10 + (-1)10= (0)10
(0 0000001)反 + (1 1111110)反 = (1 1111111)反 = ( -0 ) 有问题。
(1)10 - (2)10 = (1)10 + (-2)10 = (-1)10
(0 0000001)反 + (1 1111101)反 = (11111110)反 = (-1) 正确。
问题出现在(+0)和(-0)上,在人们的计算概念中零是没有正负之分的。(印度人首先将零作为标记并放入运算之中,包含有零号的印度数学和十进制计数对人类文明的贡献极大)。
于是就引入了补码概念。负数的补码就是对反码加一,而正数的补码不变,正数的原码反码补码是一样的。在补码中用(-128)代替了(-0),这个是人为规定的,所以补码的表示范围为:
(-128~0~127)共256个。
注意:(-128)没有相对应的原码和反码, (-128) = (1 0000000) 补码的加减运算如下:
(1)10 - (1)10 = (1)10 + (-1)10 = (0)10
(0 0000001)补 + (1 1111111)补 = (0 0000000)补 = ( 0 ) 正确。
(1)10 - (2)10 = (1)10 + (-2)10 = (-1)10
(00000001)补 + (11111110)补 = (11111111)补 = (-1) 正确。

所以补码的设计目的是:

原码、反码、补码
 
一、什么是原码、反码、补码

原码:将整数,转换成二进制,就是其原码。
如单字节的5的原码为:0000 0101;-5的原码为1000 0101。(最高位为符号位正为0负为1)

反码:正数的反码就是其原码;负数的反码是将原码中,除符号位以外,每一位取反。
如单字节的5的反码为:0000 0101;-5的反码为1111 1010。

补码:正数的补码就是其原码;负数的反码+1就是补码。
如单字节的5的补码为:0000 0101;-5的补码为1111 1011。

二、为什么要有这三类码

计算机只能识别0和1,使用的是二进制。而在日常生活中人们使用的是十进制,并且我们用的数值有正负之分。于是在计算机中就用一个数的最高位存放符号(0为正,1为负)。这就是机器数的原码了。
有了数值的表示方法就可以对数进行算术运算,但是很快就发现用带符号位的原码进行乘除运算时结果正确,而在加减运算的时候就出现了问题,如下:假设字长为8bits
(1) 10 - (1)10 = (1)10 + (-1)10 = (0)10
(0 0000001)原 + (1 0000001)原 = (1 0000010)原 = ( -2 ) 显然不正确。
因为在两个整数的加法运算中是没有问题的,于是就发现问题出现在带符号位的负数身上。对除符号位外的其余各位逐位取反就产生了反码。反码的取值空间和原码相同且一一对应。下面是反码的减法运算:
(1)10 - (1)10 = (1)10 + (-1)10= (0)10
(0 0000001)反 + (1 1111110)反 = (1 1111111)反 = ( -0 ) 有问题。
(1)10 - (2)10 = (1)10 + (-2)10 = (-1)10
(0 0000001)反 + (1 1111101)反 = (11111110)反 = (-1) 正确。
问题出现在(+0)和(-0)上,在人们的计算概念中零是没有正负之分的。(印度人首先将零作为标记并放入运算之中,包含有零号的印度数学和十进制计数对人类文明的贡献极大)。
于是就引入了补码概念。负数的补码就是对反码加一,而正数的补码不变,正数的原码反码补码是一样的。在补码中用(-128)代替了(-0),这个是人为规定的,所以补码的表示范围为:
(-128~0~127)共256个。
注意:(-128)没有相对应的原码和反码, (-128) = (1 0000000) 补码的加减运算如下:
(1)10 - (1)10 = (1)10 + (-1)10 = (0)10
(0 0000001)补 + (1 1111111)补 = (0 0000000)补 = ( 0 ) 正确。
(1)10 - (2)10 = (1)10 + (-2)10 = (-1)10
(00000001)补 + (11111110)补 = (11111111)补 = (-1) 正确。

三、所以补码的设计目的是:
⑴ 使符号位能与有效值部分一起参加运算,从而简化运算规则。补码机器数中的符号位,并不是强加上去的,是数据本身的自然组成部分,可以正常地参与运算。
⑵ 使减法运算转换为加法运算,进一步简化计算机中运算器的线路设计。
所有这些转换都是在计算机的最底层进行的,而在我们使用的汇编、c等其他高级语言中使用的都是原码。

⑴ 使符号位能与有效值部分一起参加运算,从而简化运算规则。补码机器数中的符号位,并不是强加上去的,是数据本身的自然组成部分,可以正常地参与运算。
⑵ 使减法运算转换为加法运算,进一步简化计算机中运算器的线路设计。
所有这些转换都是在计算机的最底层进行的,而在我们使用的汇编、c等其他高级语言中使用的都是原码。
/***********************

计算机补码与原十进制数的转换

正数:
正数补码 = 自身对应二进制数

e.g. 27 = 0001 1011

负数:
负数 -->补码:
取得负数的绝对值的二进制数字
按位取反
加1
e.g: -86 = 1010 1010

过程示例:
|-86|= 86,86 --> 0101 0110

0101 0110 :按位取反指是0的位取1,是1的位取0

​ 故有:1010 1001

加1:1010 1001 + 1 = 1010 1010

-86补码为 1010 1010

补码 --> 负数:
法一:
逆过程即可

法二:
首位取负,其余位取正,乘对应权重:

/************************补码与有符号数范围判断

一、补码
先说概念,

机器数:一个数在计算机中的二进制表示形式,带符号,最高位是符号位,正数为0,负数为1

真值:因为机器数带符号,直接按照二进制转换的话,得到的数值不一定是存储的真正的数值,所以机器数表示的实际的那个值,叫真值,例如1000 0001的真值 = –000 0001 = –1。

原码:符号位加上真值的绝对值, 即用第一位表示符号, 其余位表示值。对于8bit数,其取值范围是:[1111 1111 , 0111 1111],也就是[-127 , 127],这个被叫做人脑最容易理解和计算的表示法。

反码:正数的反码是其本身,负数的反码是在其原码的基础上,符号位不变,其余各个位取反。

补码:正数的补码就是其本身,负数的补码是在其原码的基础上,符号位不变,其余各位取反,最后 +1。(即在反码的基础上 +1)。

补码的出现是为了让符号位参与到运算中。

如果直接是原码来参与,会出现如下结果:

1 - 1 = 1 + (-1) = [00000001]原 + [10000001]原 = [10000010]原 = -2

这结果显然是不对的,所以出现了反码,使用反码参与计算时:

1 - 1 = 1 + (-1) = [0000 0001]原 + [1000 0001]原= [0000 0001]反 + [1111 1110]反 = [1111 1111]反 = [1000 0000]原 = -0

计算结果的真值是没问题的,但是对于结果0,对于实际的运算,+0和-0是一样的东西(数学中,对于极限等证明时,会区分+/-0),0带符号没啥意义,而且这样会出现[0000 0000]原 和 [1000 0000]原 两个编码分别表示了+0和-0,用2个编码保存一样的数非常浪费。

所以使用补码:

1-1 = 1 + (-1) = [0000 0001]原 + [1000 0001]原 = [0000 0001]补 + [1111 1111]补 = [0000 0000]补=[0000 0000]原

这个时候,0可以用[0000 0000]表示,-0就没了。

然后这个[1000 0000]这个数呢,就表示-128了,为什么,因为

128 = -127-1 = [1000 0001]补 - [0000 0001]补 = 1000 0000
所以,使用补码表示时,解决了有符号数中+0和-0的问题,并且还可以多保存一个最小值。

因此,使用原码和反码表示时,是无法出来-128的,现代计算机对于有符号数,都是采用补码表示,所以**8bit范围是-128~127,**其他有符号的数也同理。

二、有符号数范围判断
依旧以8bit有符号数为例,记为a,判断该有符号数属于[-16~15]。

真值    -16    15
原码    1001 0000    0000 1111
补码    1111 0000    0000 1111
有符号数属于【-16~15】范围内,则有高四位为全1或全0.

因此可以得到逻辑表达式:

&a[7:4] | &~a[7:4]
展开为
a[7] & a[6] & a[5] & a[4] | ~a[7] & ~a[6] & ~a[5] & ~a[4] 

 

  • 10
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值