首页 > 编程知识 正文

补码的补码是原码,如何求反码和补码

时间:2023-05-03 23:09:30 阅读:174717 作者:389

如果没有原码、反码、补码的概念,如何表示负数? 原来机器只能表示正数,8位二进制文件是0到255,也就是[ 00000000,11111111 ]。

为了让计算机理解负数,科学家想出了一个方法

现在,要表示负数,最高0表示正数,1表示负数。 本来8位表示一个数的大小,但现在变成了7位。 其中,[0 ~ 127]没有变化。 本来的[128 ~ 255]是用来表示负数的。 其中原来的128是-128,原来的255是-1。 例如,255的16位以下的后8位为[11111111],较强的情况下,转移到byte类型时为-1[11111111];

原码、反码、补充码是什么? 数在计算机中的二进制表示,称为此数的机器数。

有符号数和无符号数是针对符号出现的2种机器数量的表示方法。 同是二进制数,有符号的数和没有符号的数有不同的含义。

有char、short、int、long等类型的变量

无符号数字(在c语言中)例如,类型为unsigned char、unsigned short、unsigned int、unsigned long和指针的变量

计算机中有符号的数据有源代码、反转代码、补充代码三种表示方法。 三种显示方法都有两个部分:已编码比特和数字比特,已编码比特都由0表示“正”,由1表示“负”,并且数字比特的三种显示方法彼此不同。 在计算机系统中,数值都用补码表示和存储。 这是因为,通过使用补数,能够将编码比特和数值字段统一地处理; 同时,加法和减法也可以统一处理。

原来的代码是用数字的二进制表示法从左到右的第一位,即最高位为符号位。 正数是0,负数是1。 (请注意,原始0有两种表示形式: 0和-0。 )剩下的位数表示数值的大小。

在反转显示方法中,正数的反转代码与原来的代码相同,负数的反码将正数逐比特反转,符号比特保持为1。

换句话说,反向代码是对除了原代码的代码位之外的所有位分别对1进行异或(^ )操作后的结果。

补数是指在反码上加1的结果。

因为看了以上的定义也不知道,所以以32位的整数1和-1为例。

给定给定一个int整数I,如果I是负数,则I的反向代码的值为(I ) integer.max_value,补充代码的值为(I ) integer.max_value,如果I是正数,则反向代码

其中: Integer.MAX_VALUE=2147483647,其原代码: [ 011111111111111111111111111111111 ]

说白了,反符号和补数是为负数设定的,但反符号是补数的转移产物,没有实际意义。 我们需要记住的是负数的原码和补码的关系和导出过程。 在计算机中所有负数都用补数表示,所以必须记住负数的补数是如何导出原码的。

如何从源代码中导出补数? int太长太麻烦了,我们以byte类型(8位)为例。

1

源代码: [ 00000001 ]

(不变) )

反码: [ 00000001 ]

(不变) )

补数: [ 00000001 ]

-1

源代码: [ 10000001 ]

(除符号位外逐位反转)

反码: [ 11111110 ]

(1) ) ) )。

补数: [ 11111111 ]

127

原代码: [ 01111111 ]

反码: [ 01111111 ]

补数: [ 01111111 ]

因为源代码的第一位是符号位,所以byte型的8位二进制的可取范围是:

[ 1111111,01111111 ]即

[-127,127 ]

(这个时候,可能也会有同学会说你是博主,有水货。 byte整形的可取值范围是-128~127,但不要着急。 请继续往下看。 )

从补数中导出原始代码的方法-1

补数: [ 11111111 ]

(除符号位外逐位反转)

反码: [ 1000000 ]

(1) ) ) )。

源代码: [ 10000001 ]

和负数的原码引导补数的过程不一样吗? 因此,记住补数的补数就是原码的总结。 在二进制数字中,二进制补数之和等于二进制补数。

负数的反码=使除了原始码的编码比特以外的其他比特的数值相反。 即,“0”变为“1”,“1”变为“0”。

负数补数=反码1

负数源代码=负数补码的反码1

正数的源代码、反码、完成码都是一样的。 (也就是说,自己不会改变)。

在计算机中,有符号的数都用补数表示

计算时,符号位也可以参加运算。

那么,原码、反码和补码的作用是什么呢? 1 .使用补码可以将已编码比特和其他比特统一处理; 另外,减法也可以用加法处理。

2 .补码不仅可以修正0的符号和2个符号的问题,还可以多表示一个最低数。 因此,八位二进制码元表示的范围

[-127, +127], 而使用补码表示的范围为[-128, 127]。
举个例子
(-1) + (-127) = 原码:[1000 0001] + 原码:[1111 1111]

                    = 补码: [1111 1111] + 补码:[1000 0001]

                    = 补码: [1000 0000]

                    = -128

-1-127的结果就是-128, 有符号的数都是采用补码来表示的, 所以补码:[1000 0000] 就是-128.。

但是注意[1000 0000]实际上是使用以前的-0的补码来表示-128, 所以现在-0是被当作0来处理了(虽然有点绕,你只要记得-0被丢弃就行了)。

对于-128在有符号的8位进制下是得不到补码的,因为按照约定最高位是符号位,而它的低7位都是0,

所以-128其实是数溢出了,对于补码表示[1000 0000]逆推得到的原码是[0000 0000], 这又是不正确的。

假如-128是32位整数,那么他此时的对应的补码就是[11111111 11111111 11111111 10000000]。

其中:

0 (在编译器中-0会被转为0表示,规定-0的补码用来表示当前位数下最大的负数)
原码:[ 00000000 ]
反码:[ 00000000 ]
补码:[ 00000000 ] 另一个我需要强调的就是数的溢出问题,

n位bit位的整数,所能表示的范围是[-2^(n-1), 2^(n-1)-1]

一旦数字超过了这个限定,就会发生溢出,超过上限,叫做上溢出。超过下限,叫做下溢出。上溢出之后,又从下限开始:最大的数加1,就变成了最小的数。下溢出之后又从上限开始,最小的数减去1就变成了最大的数,如此循环往复。

如果一个N位数经过运算得到了一个N+1位的数,那么此时他的最高位就是溢出状态,是直接被舍弃的,举个例子:
一个无符号数255在byte(8位)类型中的二进制形式为255[ 11111111 ],如果此时对它进行加1操作,则会变成0[ 00000000 ],此时就发生了数的溢出,而如果它是一个short(16位)类型,其二进制形式便是255[ 00000000 11111111],加1后的结果为256[ 00000001 00000000],便没有发生溢出。

也许我说了这么多,你还是没明白,简而言之,反码只是原码得到补码的一个过渡产物,并无什么实际意义,你需要记住的是原码是给人看的,而补码是给机器看的。对于机器而言,它其实并没有负数的概念,在对负数的原码进行运算的时候,它其实是无能为力的,所以需要引入负数的补码表示一个负数。 那么问题来了,为什么机器对负数的补码进行算术运算操作就能得出正确的结果呢? 这边要引入同余的概念 定义:两个整数a、b,若它们除以整数m所得的余数相等,则称a与b对于模m同余或a同余于b模m。 或者说:给定一个正整数m,如果两个整数a和b满足a-b能够被m整除,即(a-b)/m得到一个整数,那么就称整数a与b对模m同余,记作a≡b(mod m)。

定义三个变量分别为a、b、m.
我们取a=-1 ,m= 256;
假设 (a-b)/m = -1,可以得到 b = 255,所以我们可以说-1和255同余
我们再以 c = a + b举例,其中c为有符号的byte类型,显然c小于256,可以得到:
c = c ^ (256 - 1) = c mod 256
   = (-1 + 127)mod 256
   = (255 + 127) mod 256
   = (255 + 1 + 126) mod 256
   = (256 + 126) mod 256
   = (0 + 126) mod 256
   = 126 [ 01111110 ]
我们用a+b得到结果126,对于机器而言过程如下:

讲到这你应该明白为什么负数的补码=原码的反码加1了吧

定义一个byte x = -1 ;
原码:[ 10000001 ]
反码: [ 11111110 ] = 254 = 256 -1 - |x|
补码: [ 11111111 ] = 255 = 256 - |x|
对于byte类型x;它的补码就是2^8 - x的绝对值

想一想要是你要原码直接做加法,会是什么情况?

(-1) + 127 = 原码:[ 1000 0001 ] + 原码:[ 1111 1111 ]
                 = 原码:[ 10000000 ]
                 = -128

你没看错结果就是-128,显然这是不对的,那么你又要问了,难道机器不会做减法吗?我要说的是----没错,机器还真的不会减法,现在你看到的减法其实就是对负数做加法运算而已。 同样是上面的例子我们再来变通一下:

(-1) + 127 = 原码:[ 1000 0001 ] + 原码:[ 0111 1111 ]
                 = 补码:[ 1111 1111 ] + 补码: [ 0111 1111 ]
                 = 255 + 127 (还是那句话计算机不理解负数,对它而言-1的补码其实就是255的原码,这也是为什么byte类型下127+1结果显示-128的原因)
                 = 126

对,你还是没看错,255+127对于机器得到的结果就是126,原理就是前面讲过的数的溢出问题。

我们把byte类型的取值区间想象成一个圆环,它的周长是256,我们把它分为256份也就是256个点,每相邻两个点间距为1,如下图:

所以127 + 255 相到于从127这个点顺时针走了255个点,最后正好落在了126这个点位上,同理127 - 1 就是127这个点逆时针走了一个点,也是落在了126上。

(-1) + 127 则相当于从-1这个点顺时针出发经过127个点到了126上。

题外话:古人对南辕北辙有误解,因为地球是圆的,所以,只要一直往南,那么是能到北的。

说了这么多,其实同余理不理解已经无所谓了 对于我们可以这样理解(mod为取模操作):

(-1) + 127 = ((-1) + 127)mod 256
                 =([ 11111111 ] + 127 )mod 256
                 =(255 + 127 )mod 256
                 =    126

重要的事情再说一遍:一个8位数(16位或更高位的同理)可以表示的数其实是[0 ~ 255],但是因为我们要让计算机可以表示负数于是规定了[0 ~ 127]不变,原本的[128 ~ 255]就被用来表示负数了(对应上面的圆)。

我们站在计算机的角度看它如何理解这一个过程:

我们看到的是实际值:(-1) ,计算机看到的是补码: [ 11111111 ] ,所以计算机理解的值就是255[ 11111111 ],但是由于最高位表示符号,就取低7位的值127,而-127的原码即为-1。但是我们注意到在8位字节数中,是不存在256的,且小于256,所以255 mod 256的这部操作就相当于:
255[ 11111111 ] ^ 127[ 01111111 ] + 1[ 00000001] = 128[ 10000001] = -[ 0000001 ] = -1最高位若是1输出符号位(-),剩下低位则正常输出,就是这么一个过程。 、若有不理解的请在下方留言哈…

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。