最新消息:XAMPP默认安装之后是很不安全的,我们只需要点击左方菜单的 "安全"选项,按照向导操作即可完成安全设置。

原码,反码和补码有什么不同?源码 反码 补码 详解

XAMPP教程 admin 24浏览 0评论
我们知道计算机语言可以简单概括为三类,分别是机器语言、汇编语言和高级语言。机器语言是由二进制组成的编码,由无数个0和1组成。在二进制系统中,每个0或1就是一个位,而位是数据存储的最小单位,可称之为比特(Bit)。在计算机高级语言(Java)中,整数类型变量中有字节型(byte),它与比特的换算关系为1byte=8bit,也就是1个字节等于8个比特。
8个比特在二进制编码中的表现形式(以数1为例)是这样的:
0000 0001
 
转换为十进制数就是2^0=1
而在一般情况下它能表示的最大范围数为
1111 1111
最小范围数为
0000 0000
 
最大范围数转换为十进制数也就是2^8-1=255,最小范围数为0,范围为0~255。而实际字节型(byte)的取值范围却为-2^7~2^7-1即-128~127,这是为什么呢?
现代数学中数字有大小和正负之分,可以进行算术运算(加减乘除),然而对于计算机来说,数字都是以无符号位的二进制数表示,它既分不清大小,也分不清正负。为了解决这个问题,就引入了原码、反码、补码这个概念。
我们先看原码的定义:
原码(true form)是一种计算机中对数字的二进制定点表示方法。原码表示法在数值前面增加了一位符号位(即最高位为符号位):正数该位为0,负数该位为1(0有两种表示:+0和-0),其余位表示数值的大小。——百度百科
计算机中所有的数均用0、1编码表示,数字的正负号也不例外,如果一个机器数字长是n位的话,约定最左边一位用作符号位,其余n-1位用于表示数值。——维基百科
对于字节型来说,符号位(从右向左最后一位)决定正负而不参与数值运算,在原码中,0000 0000代表十进制数0,1000 0000代表十进制数-0,而0000 0001代表十进制数1,1000 0001代表十进制数-1,我们可以观察到他们的异同:
相同之处:
对于±0和±1,最高位(符号位)都决定了它们的正负情况。
不同之处:
对于+0和-0来说,现实中运算并没有正负之分,也就是它们应该是相等的。一个字节共8位,其中7位表示数,一位代表符号,这样的结果就是0000 0000和1000 0000都可以表示为0。在最初是通过CPU执行两次比较来识别±0的,但是这种方式不仅增加了成本,也给电路的设计带来了挑战,最终经由补码来解决这个问题。
原码的优点在于简单直观的反映了一个数的大小正负情况,然而它却不能直接参与减法运算
以1-1为例,计算机中减法运算可以理解为正数+负数,故1-1在计算机实际运算中等于1+(-1),也就是
                                0000 0001
                            +
                                1000 0001
                            =
                                1000 0010
十进制数为-2,可知原码直接参与负数运算是不被允许的
反码就是用来解决原码运算问题的过渡码:
反码的概念:
反码通常是用来由原码求补码或者由补码求原码的过渡码。根据定义,可以得到机器数的反码的整数和小数中“0”的表示形式各有2种,“+0”和“-0”不一样,以8位机器数为例,整数的“+0”原码为0,0000000,反码为0,0000000;整数的“-0”原码为1,0000000,反码为1,1111111;小数的“+0”原码为0.0000000,反码为0.0000000;小数的“-0”原码为1.0000000,小数的“-0”反码为1.1111111。反码跟原码是正数时,一样;负数时,反码就是原码符号位除外,其他位按位取反。[1]——百度百科
可知对于正数来说,反码=原码,对于负数来说,反码=符号位不变,其它位按位取反
我们看看反码在二进制的运算情况
以1-1为例
1的原码0000 0001
1的反码0000 0001
-1的原码1000 0001
-1的反码1111 1110
也就是
                                0000 0001
                            +
                                1111 1110
                            =
                                1111 1111
1111 1111转换为原码得1000 0000,十进制也就是-0
以1-2为例
1的原码0000 0001
1的反码0000 0001
-2的二进制;
-2的原码1000 0010
-2的反码1111 1101
也就是
                                0000 0001
                            +
                                1111 1101
                            =
                                1111 1110
1111 1110转换为原码得1000 0001 ,十进制也就是-1
以2-1为例
2的原码0000 0010
2的反码0000 0010
-1的原码1000 0001
-1的反码1111 1110
也就是
                                0000 0010
                            +
                                1111 1110
                            =
                              1 0000 0000
实际位数为8,这里有9位,所以最高位1溢出被自动舍弃,即为0000 0000,原码0000 0000,十进制为0
以-1-1为例
-1的原码1000 0001
-1的反码1111 1110
也就是
                                1111 1110
                            +
                                1111 1110
                            =
                              1 1111 1100
实际位数为8,这里有9位,所以最高位1溢出被自动舍弃,即为1111 1100,原码为1000 0011十进制为-3,同理-1-2结果为-4
由上面的例子可以发现些许问题,反码计算中,某些情况下(如2-1)实际正确值=实际结果值-1,如果结果为±0,那么+0和-0的区分也存在问题,如果正数+负数<0结果正确,反码无疑也是行不通的,由此便引入了补码的概念(注意:补码的运算中最高位是参与运算的,相当于无符号位运算)。
在介绍补码概念之前,先介绍一下“模”的概念:“模”是指一个计量系统的计数范围,如过去计量粮食用的斗、时钟等。计算机也可以看成一个计量机器,因为计算机的字长是定长的,即存储和处理的位数是有限的,因此它也有一个计量范围,即都存在一个“模”。如:时钟的计量范围是0~11,模=12。表示n位的计算机计量范围是0-2^n-1,模=2^n.“模”实质上是计量器产生“溢出”的量,它的值在计量器上表示不出来,计量器上只能表示出模的余数。任何有模的计量器,均可化减法为加法运算 [3]  。
假设当前时针指向8点,而准确时间是6点,调整时间可有以下两种拨法:一种是倒拨2小时,即8-2=6;另一种是顺拨10小时,8+10=12+6=6,即8-2=8+10=8+(12-2)(mod 12).在12为模的系统里,加10和减2效果是一样的,因此凡是减2运算,都可以用加10来代替。若用一般公式可表示为:a-b=a-b+mod=a+(mod-b)。对“模”而言,2和10互为补数。实际上,以12为模的系统中,11和1,8和4,9和3,7和5,6和6都有这个特性,共同的特点是两者相加等于模。对于计算机,其概念和方法完全一样。n位计算机,设n=8,所能表示的最大数是11111111,若再加1成100000000(9位),但因只有8位,最高位1自然丢失。又回到了 00000000,所以8位二进制系统的模为2^8。在这样的系统中减法问题也可以化成加法问题,只需把减数用相应的补数表示就可以了。把补数用到计算机对数的处理上,就是补码 [3]  。
——摘自百度百科
概念中巧妙的用到了时钟来举例,假设当前时间为8点,要调到6点,有两种办法:一种是往回调拨2小时(逆时针),即8-2=6;另一种是往后顺拨10小时(顺时针),即8+10=6。这里用到了同余的概念,而不是简单地相加减。我们知道时钟从1到12类似首尾相连,衔接成一个圆,12点过后会回转到1点,而不会向上叠加为13、14等,12就是时钟的模。我们发现期望结果=8-2=8+(模=12-2)=8+10。
这里也可以以东南西北方位为例,假设指针所指为北边,要转到为西边,可以逆时针转90°,也可以顺时针转270°(360°-90°),360°就是方位的模。

西    ↑    东
8位的计算机每位的变化量为2,要么为0要么为1,所以总共能表示的数据有2^8=256个,无符号值的范围为0000 0000~1111 1111,也就是0~2^8-1即0~255,256即为字节型的模(这点有疑惑的可参照数组的特点,相当于索引从0~255,但实际长度为索引最大值255+1)。
如果数值大于255如1 0000 0000(十进制为2^8=256)则最高位1丢失,最终变成0000 0000,相当于时钟走过12点又回到1点。故计算机8位的模256=1111 1111+0000 0001(数1)=最高位数值+1。
推导过程:
这里的运算相当于无符号运算
以8-2为例,同理,8-2=8+(-2)=8+(计算机8位的模-2)
计算机8位的模-2=1111 1111+0000 0001(数1)-0000 0010(数2)            =1111 1111-0000 0010(数2)+0000 0001(数1)              而1111 1111- 0000 0010(数2)=1111 1101=数(-2)的反码
0000 0001(数1)+1111 1101=1+数(-2)的反码=数(-2)的补码
故计算机8位的模-2=数(-2)的补码
所以8-2=8+(计算机8位的模-2)=8+数(-2)的补码
8的二进制:
原码0000 1000
反码0000 1000
补码0000 1000
-2的二进制:
原码1000 0010
反码1111 1101
补码1111 1110
故8-2=8+(-2)=
                                0000 1000
                            +
                                1111 1110
                            =
                            1  0000 0110
实际位数为8,这里有9位,所以最高位1溢出被自动舍弃,即为0000 0110,化为十进制数为2^2+2^1=6
由上面的推导公式可以发现规律:
计算机8位的模=最高位(1111 1111)+1
a-b=a+(计算机8位的模-b)
计算机8位的模-b=最高位-b+1
最高位-b=-b的反码
-b的反码+1=-b的补码
a-b=a+(-b)的补码
可知对于正数来说,补码=反码=原码;对于负数来说,反码=原码符号位不变,其它位按位取反,补码=反码+1
以以下几个例子来做测试:
1-2=1+(-2)
1的二进制:
原码0000 0001
反码0000 0001
补码0000 0001
-2的二进制:
原码1000 0010
反码1111 1101
补码1111 1110
故1-2=1+(-2)=
                                0000 0001
                            +
                                1111 1110
                            =
                                1111 1111
减1,转换为反码1111 1110,转换为原码1000 0001,十进制为-1
2-1=2+(-1)
2的二进制:
原码0000 0010
反码0000 0010
补码0000 0010
-1的二进制:
原码1000 0001
反码1111 1110
补码1111 1111
故2-1=2+(-1)=
                                0000 0010
                            +
                                1111 1111
                            =
                             1 0000 0001
实际位数为8,这里有9位,所以最高位1溢出被自动舍弃,0000 0001由符号位可知为正数,其原码、反码、补码相等,将0000 0001转换为十进制数为1*2^0=1
1-1=1+(-1)
1的二进制:
原码0000 0001
反码0000 0001
补码0000 0001
正数的原码、反码、补码是一致的
-1的二进制:
原码1000 0001
反码1111 1110
补码1111 1111
负数的反码为原码符号位不变,其它位取反
负数的补码为反码+1
故1-1=1+(-1)=
                                0000 0001
                            +
                                1111 1111
                            =
                             1 0000 0000
实际位数为8,这里有9位,所以最高位1溢出被自动舍弃,0000 0000的原码、反码、补码都是0
解答:
可知1个字节占8位,能表示的数据有2^8=256个。
二进制数范围为0000 0000~1111 1111即0~255,把它当作无符号数划分开来,可区分为0000 0000~0111 1111(0~127)和1000 0000~1111 1111(128~255),分别对应正负数。正数分到的区间为0000 0000~0111 1111,负数分到的区间为1000 0000~1111 1111。
已知补码相当于无符号数,对正数而言,原码=反码=补码,故字节型正数原码范围0000 0000~0111 1111一一对应0000 0000~0111 1111(0~127),即原码1(0000 0001)对应补码0000 0001(无符号数值1),原码127(0111 1111)对应补码0111 1111(127),共有128个数据;对负数而言,补码=原码取反+1,以原码-1为例,原码-1(1000 0001)对应的补码为1111 1111(无符号数值255),原码-2(1000 0001)对应的补码为1111 1110(无符号数值254)……原码-127(1111 1111)对应的补码为1000 0001(无符号数值129),剩下最后一个,原码-0(1000 0000)对应的补码为1000 0000(无符号数值128),可知0~255区间每个数都是独立不重复的,如果按照实际取值,-0对应无符号数值128,而规定的0的二进制数为0000 0000对应补码0000 0000(无符号数值0),“一山不容二虎”,为了保持独立性,规避±0区分问题,计算机中直接硬性规定1000 0000原码的实际值为-128,对应的补码为1000 0000(无符号数值128),所以负数的取值范围为-128~-1,有128个数据。
所以字节型(byte)的取值范围为(-128~-1)∪(0~127)为-2^7~2^7-1即-128~127。
补充:
2^0+2^1+……2^n=(2^n)-1
2进制数转换为10进制数
如0111 1111=2^6+2^5+2^4+2^3+2^2+2^1+2^0=2^7-1=127
除原码、反码、补码外还有移码
 
移码(又叫增码)是符号位取反的补码,一般用指数的移码减去1来做浮点数的阶码,引入的目的是为了保证浮点数的机器零为全0。——百度百科
若0111 1111为补码,则移码为1111 1111
以下是给我以启迪的链接,在此表示特别感谢

转载请注明:XAMPP中文组官网 » 原码,反码和补码有什么不同?源码 反码 补码 详解