关于-128,+128,-0,+0,-1的反码补码
⼀.反码的范围
反码表⽰法规定:正数的反码与其原码相同。负数的反码是对其原码逐位取反,但符号位除外。
在规定中,8位⼆进制码能表⽰的反码范围是-127~127。
此时(字长为8位), -128没有原码和反码(只有补码)。
那么,为什么规定字长8位时-128没有原码和反码呢?下⾯解释。
⾸先看-0,[-0]原码=1000 000,其中1是符号位,求反操作,算出[-0]反码=1111 1111,
再看-128,假如它有原码且[-128]原码=1000 000,假如让-128也有反码,求反操作,则[-128]反码=1111 1111,
你会发现,-128的反码和-0的反码相同,所以为了避免⾯混淆,有了-0的原码,便不能有-128的原码补码,这是8位⽐特位位数限制决定的。
⼆.原码反码补码的范围
前提:字长是8位⼆进制数。
两个负数的补码相加原码 -127~127 (-128没有原码反码,原因看前⾯解释~)
反码 -127~127
补码 -128~127
对于n位⼆进制数:
你会发现,补码⽐其它码多⼀位,这是为什么呢?问题出在0上。
[+0]原码=0000 0000, [-0]原码=1000 0000
[+0]反码=0000 0000, [-0]反码=1111 1111
[+0]补码=0000 0000, [-0]补码=0000 0000
你会发现,+0和-0的补码是⼀样的。即 0的补码只有⼀种表⽰。
这⾥解释⼀下[-0]补码是怎么得来的。
负数的补码就是反码整体加⼀。符号位上的进位舍弃。(所以,舍弃了符号位的补码的第⼀位是数值位,不是符号位,符号位舍弃了)
另外解释⼀下原码符号位和补码符号位的关系,补码的符号位不是保持原码的第⼀位不变,⽽是符号位不变,[-0]反码的第⼀个1是符号位,尾数中的7个1是数值位,尾数加⼀后,数值位产⽣了进位,1111 1111+1=1 0000 0000(计算补码的过程中,并不是先保证第⼀位不变,⽽是保证符号位不变,保证补码规则是反码整体加⼀)。
所以,补码能表⽰的数的个数中,⽐原码反码少了⼀个,所以补码可以多表⽰⼀个真值为-128的数。
但是,多表⽰的这个数-128⽐较特殊,只有原码和补码,没有反码。
-128的补码是1000 0000。
三.-128的补码为什么是1000 0000
8位⼆进制的原值表达范围为:-127⾄127
共有256个组合序列 0000 0000 ⾄1111 1111 。
+128的原值在8位中是表达不出来的。
下⾯从两个⾓度理解-128的补码为什么是1000 0000.
(1)从补码的意义上去理解
因为:256-128=256+(-128)的补码 --机器中只有加法。减法会变成补码的加法。
⽽ 256-128=128
所以 256+(-128)的补码=128
所以(-128)的补码=256-128
=128
数学上, 128=1000 0000
故规定-128的补码为 1000 0000
注意:只是规定⽽已,下⾯还有原因。
8位⼆进制的补码组合序列有256个
0000 0000 - 0111 1111 0 ~+127
1000 0000 ⽤来⼲啥好呢?
1000 0001 - 1111 1111 -1~-127
再看看这个规律表
原码补码值
0111 1111 0111 1111 +127
0111 1110 0111 1110 +126
.
.. .. 补码不断-1...
0000 0000 0000 0000 0
1000 0001 1111 1111 -1
1000 0010 1111 1110 -2
1000 0011 1111 1101 -3
... .. 补码不断-1...
1111 1111 1000 0001 -127
⽆法表达 1000 0000 -128
于是就有了规定 1000 0000 定为 -128的补码
这种定法和上⾯数学层⾯的表述是⼀致的。
这样规定后,负数的补码在机器中就好算了。
计算⽅法上是:
将该负数取绝对值,再⽤⼆进制表⽰出这个绝对值 (不管符号位!)
对该⼆进制数进⾏取反加⼀操作就得到负数的补码了(也就是求补操作!)
-128 绝对值是 128
128的⼆进制表⽰为:
1000 0000
取反
0111 1111
加1
1000 0000
这就是-128的补码
这种办法算出的结果符合“规定值”。
四.
1字节 = 8位,所以它能表⽰的最⼤数当然是8位都是1(既然2进制的数只能是0或1,如果是我们常见的10进制,那就8位都为9,这样说,你该懂了?)
1字节的⼆进制数中,最⼤的数:11111111。
双字节共16位。 1111111111111111。双字节数最⼤值为:
1 * 215 + 1 *214 + 1* 213 + 1 * 21
2 + 1 * 211 + 1 * 210 + …… + 1 * 22 + 1 * 21 + 1* 20 = 65535
负数在计算机中如何表⽰呢?
这⼀点,你可能听过两种不同的回答。
⼀种是教科书,它会告诉你:计算机⽤“补码”表⽰负数。可是有关“补码”的概念⼀说就得⼀节课,这⼀些我们需要在第6章中⽤⼀章的篇幅讲2进制的⼀切。再者,⽤“补码”表⽰负数,其实是⼀种公式,公式的
作⽤在于告诉你,想得到问题的答案,应该如何计算。却并没有告诉你为什么⽤这个公式就可以得到答案! -----我就是被这个弄混淆的>_<
另⼀种是⼀些程序员告诉你的:⽤⼆进制数的最⾼位表⽰符号,最⾼位是0,表⽰正数,最⾼位是1,表⽰负数。这种说法本⾝没错,可是如果没有下⽂,那么它就是错的。⾄少它不能解释,为什么字符类型的-1⽤⼆进制表⽰是“1111 1111”(16进制为FF);⽽不是我们更能理解的“1000 0001”。(为什么说后者更好理解呢?因为既然说最⾼位是1时表⽰负数,那1000 0001不是正好是-1吗?-----re!当初偶就是这么想的,so⼀直在脑中打架,越打越混淆=,=)。
让我们从头说起。
2.1、你⾃已决定是否需要有正负。
就像我们必须决定某个量使⽤整数还是实数,使⽤多⼤的范围数⼀样,我们必须⾃已决定某个量是否需要正负。如果这个量不会有负值,那么我们可以定它为带正负的类型。
在计算机中,可以区分正负的类型,称为有符类型,⽆正负的类型(只有正值),称为⽆符类型。
数值类型分为整型或实型,其中整型⼜分为⽆符类型或有符类型,⽽实型则只有有符类型。
字符类型也分为有符和⽆符类型。
⽐如有两个量,年龄和库存,我们可以定前者为⽆符的字符类型,后者定为有符的整数类型。
3、⽆符号数和有符号数的范围区别。
同样是⼀个字节,⽆符号数的最⼤值是255,⽽有符号数的最⼤值是127。原因是有符号数中的最⾼位被挪去表⽰符号了。并且,我们知道,最⾼位的权值也是最⾼的(对于1字节数来说是2的7次⽅=128),所以仅仅少于⼀位,最⼤值⼀下⼦减半。
不过,有符号数的长处是它可以表⽰负数。因此,虽然它的在最⼤值缩⽔了,却在负值的⽅向出现了伸展。我们仍⼀个字节的数值对⽐:
⽆符号数: 0 ----------------- 255
有符号数: -128 ----- 0 ----- 127
同样是⼀个字节,⽆符号的最⼩值是 0 ,⽽有符号数的最⼩值是-128。所以⼆者能表达的不同的数值的个数都⼀样是256个。只不过前者表达的是0到255这256个数,后者表达的是-128到+127这256个数。
⼀个有符号的数据类型的最⼩值是如何计算出来的呢?
有符号的数据类型的最⼤值的计算⽅法完全和⽆符号⼀样,只不过它少了⼀个最⾼位(见第3点)。但在负值范围内,数值的计算⽅法不能直接使⽤1* 26 + 1* 25的公式进⾏转换。在计算机中,负数除为最⾼位为1以外,还采⽤补码形式进⾏表达。所以在计算其值前,需要对补码进⾏还原。这⾥,先直观地看⼀眼补码的形式:
以我们原有的数学经验,在10进制中:1 表⽰正1,⽽加上负号:-1 表⽰和1相对的负值。
那么,我们会很容易认为在2进制中(1个字节): 0000 0001 表⽰正1,则⾼位为1后:1000 0001应该表⽰-1。
然⽽,事实上计算机中的规定有些相反,请看下表:
⼆进制值(1字节)⼗进制值
1000 0000红⾊的1代表负数蓝⾊的是补码(补码=反
码+1)
-128
1000 0001蓝⾊部分代表多⼤的值?:将补码还原为原码-127想化成负数?:先减去1再按位取反
1000 0010还原⽅法:补码-1再取反-126
1000 0011-125
......
1111 1110-2
1111 1111-1
⾸先我们看到,从-1到-128,其⼆进制的最⾼位都是1(表中标为红⾊),正如我们前⾯的学。
然后我们有些奇怪地发现,1000 0000 并没有拿来表⽰ -0;⽽1000 0001也不是拿来直观地表⽰-1。事实上,-1 ⽤1111 1111来表⽰。
怎么理解这个问题呢?先得问⼀句是-1⼤还是-128⼤?
当然是 -1 ⼤。-1是最⼤的负整数。以此对应,计算机中⽆论是字符类型,或者是整数类型,也⽆论这个整数是⼏个字节。它都⽤全1来表⽰-1。⽐如⼀个字节的数值中:1111 1111表⽰-1,那么,1111 1111 - 1 是什么呢?和现实中的计算结果完全⼀致。1111 1111 - 1 = 1111 1110,⽽1111 1110就是-2。这样⼀直减下去,当减到只剩最⾼位⽤于表⽰符号的1以外,其它低位全为0时,就是最⼩的负值了,在⼀字节
中,最⼩的负值是1000 0000,也就是-128。
--------⼩⽶批注:就是这部分蓝⾊的⽂字,让我终于能记清楚-1的编码⽅式了,汗=。=
我们以-1为例,来看看不同字节数的整数中,如何表达-1这个数:
字节数⼆进制值⼗进制值
单字节数1111 1111红⾊表⽰负数蓝⾊部分的补码为值1-1
负数:原码就是原来
的表⽰⽅法、反码是
1111 1111 1111 1111-1
除符号位(最⾼位)
外取反、补码=反码
+1双字节数
四字节数1111 1111 1111 1111 1111 1111 1111 1111-1
可能有同学这时会混了:为什么 1111 1111 有时表⽰255,有时⼜表⽰-1?
所以我再强调⼀下本节前⾯所说的第2点:你⾃已决定⼀个数是有符号还是⽆符号的。写程序时,指定⼀个量是有符号的,那么当这个量的⼆进制各位上都是1时,它表⽰的数就是-1;相反,如果事先声明这个量是⽆符号的,此时它表⽰的就是该量允许的最⼤值,对于⼀个字节的数来说,最⼤值就是255。
ok 摘抄暂告段落,其实原⽂对于c的⼀些基础数据类型知识介绍的⾮常详细,8过太长了,摘到我需要的内容后就没全帖过来,如果有需要学习的同学,建议参见原⽂:)
转⾃
在计算机内部,所有信息都是⽤⼆进制数串的形式表⽰的。整数通常都有正负之分,计算机中的整数分为⽆符号的和带符号的。⽆符号的整数⽤来表⽰0和正整数,带符号的证书可以表⽰所有的整数。由于计算机中符号和数字⼀样,都必须⽤⼆进制数串来表⽰,因此,正负号也必须⽤0、1来表⽰。通常我们⽤最⾼的有效位来表⽰数的符号(当⽤8位来表⽰⼀个整数时,第8位即为最⾼有效位,当⽤16位来表⽰⼀个整数时,第16位即为最⾼有效位。)0表⽰正号、1表⽰负号,这种正负号数字化的机内表⽰形式就称为“机器数”,⽽相应的机器外部⽤正负号表⽰的数称为“真值”。将⼀个真值表⽰成⼆进制字串的机器数的过程就称为编码。
⽆符号数没有原码、反码和补码⼀说。只有带符号数才存在不同的编码⽅式。
带符号整数有原码、反码、补码等⼏种编码⽅式。原码即直接将真值转换为其相应的⼆进制形式,⽽反码和补码是对原码进⾏某种转换编码⽅式。正整数的原码、反码和补码都⼀样,负数的反码是对原码的除符号位外的其他位进⾏取反后的结果(取反即如果该位为0则变为1,⽽该位为1则变为0的操作)。⽽补码是先求原码的反码,然后在反码的末尾位加1 后得到的结果,即补码是反码+1。IBM-PC中带符号整数都采⽤补码形式表⽰。(注意,只是带符号的整数采⽤补码存储表⽰的,浮点数另有其存储⽅式。)
采⽤补码的原因或好处如下。
采⽤补码运算具有如下两个特征:
1)因为使⽤补码可以将符号位和其他位统⼀处理,同时,减法也可以按加法来处理,即如果是补码表⽰的数,不管是加减法都直接⽤加法运算即可实现。
2)两个⽤补码表⽰的数相加时,如果最⾼位(符号位)有进位,则进位被舍弃。
这样的运算有两个好处:
1)使符号位能与有效值部分⼀起参加运算,从⽽简化运算规则。从⽽可以简化运算器的结构,提⾼运算速度;(减法运算可以⽤加法运算表⽰出来。)
2)加法运算⽐减法运算更易于实现。使减法运算转换为加法运算,进⼀步简化运算器线路设计。
下⾯深⼊分析上⾯所陈述的采⽤补码的原因(⽬的)。
⽤带符号位的原码进⾏乘除运算时结果正确,⽽在加减运算的时候就出现了问题,如下:假设字长为8bits
1 D- 1 D = 1 D + ( -1 )D = ( 0 )D
(00000001)原 + (10000001)原 = (10000010)原 = ( -2 ) 显然不正确.。
因为在两个整数的加法运算中是没有问题的,于是就发现问题出现在带符号位的负数⾝上,对除符号位外的其余各位逐位取反就产⽣了反码。反码的取值空间和原码相同且⼀⼀对应。下⾯是反码的减法运算:
1 D- 1 D = 1 D + ( -1 )D = ( 0 )D
(00000001) 反+ (11111110)反 = (11111111)反 = ( -0 ) 有问题。
1 D -
2 D= 1 D+ ( -2 )D = ( -1 )D
(00000001) 反+ (11111101)反 = (11111110)反 = ( -1 ) 正确
问题出现在(+0)和(-0)上,在⼈们的计算概念中零是没有正负之分的。
于是就引⼊了补码概念。负数的补码就是对反码加⼀,⽽正数不变,正数的原码反码补码是⼀样的。在补码中⽤(-128)代替了(-0),所以补码的表⽰范围为:
(-128~0~127)共256个。
采⽤补码表⽰还有另外⼀个原因,那就是为了防⽌0的机器数有两个编码。原码和反码表⽰的0有两种形式+0和-0,⽽我们知道,+0和-0是相同的。这样,8位的原码和反码表⽰的整数的范围就是-127~+127(11111111~01111111),⽽采⽤补码表⽰的时候,00000000是+0,即0;10000000不再是-0,⽽是-128,这样,补码表⽰的数的范围就是-128~+127了,不但增加了⼀个数得表⽰范围,⽽且还保证了0编码的唯⼀性。
接下来的问题是,如何能将减法运算转换成加法运算呢?
我们已经知道,原码表⽰简单直观,与真值转换容易。但如果⽤原码表⽰,其符号位不能参加运算。在计算机中⽤原码实现算术运算时,要取绝对值参加运算,符号位单独处理,这对乘除运算是很容易实现的,但对加减运算是⾮常不⽅便的,如两个异号数相加,实际是要做减法,⽽两个异号数相减,实际是要做加法。在做减法时,还要判断操作数绝对值的⼤⼩,这些都会使运算器的设计变得很复杂。⽽补码这种编码⽅式实际上正是针对上述问题的。通过⽤补码进⾏表⽰,就可以把减法运算化为加法运算。
在⽇常⽣活中,有许多化减为加的例⼦。例如,时钟是逢12进位,12点也可看作0点。当将时针从10点调整到5点时有以下两种⽅法:
⼀种⽅法是时针逆时针⽅向拨5格,相当于做减法:
10-5=5
另⼀种⽅法是时针顺时针⽅向拨7格,相当于做加法:
10+7=12+5=5 (MOD 12)
这是由于时钟以12 为模,在这个前提下,当和超过12时,可将12舍去。于是,减5相当于加7。同理,减4可表⽰成加8,减3可表⽰成加9,…。
在数学中,⽤“同余”概念描述上述关系,即两整数A、B⽤同⼀个正整数M (M称为模)去除⽽余数相等,则称A、B对M同余,记作:
A=B (MOD M)
具有同余关系的两个数为互补关系,其中⼀个称为另⼀个的补码。当M=12时,-5和+7,-4和+8,-3和+9就是同余的,它们互为补码。
从同余的概念和上述时钟的例⼦,不难得出结论:对于某⼀确定的模,⽤某数减去⼩于模的另⼀个数,总可以⽤加上“模减去该数绝对值的差”来代替。因此,在有模运算中,减法就可以化作加法来做。
可以看出,补码的加法运算所依据的基本关系为:
[x]补+ [y]补= [x+y]补
补码减法所依据的基本关系式:
[x-y]补 =[x+(-y)]补= [x]补+ [-y]补
⾄于加法运算为什么⽐减法运算易于实现以及CPU如何实现各种算术运算等问题,则需要通过对数字电路的学习来理解CPU的运算器的硬件实现问题的相关内容了。
五.
1.⼀个⼆进制数的补码的补码就是原码
⽐如:真值-3,原码1000 0011,补码1111 1101,
原码1111 1101,补码1000 0011。
也可以从补码的数学含义理解。
2.⼏个特殊的补码记忆:(⼀般是8位,不是8位和8的倍数位的,在实际应⽤中没有意义,所以⼀般都是变换成成8位的⼆进制数。因为实际应⽤中,⼀般都是补码表⽰,所以着重记忆补码)
0的补码是0000 0000
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论