原码,补码,反码的由来与转换

一.原码、反码、补码的来由

     我们知道计算机只能识别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等其他高级语言中使用的都是原码。

二.原码、反码、补码之间的转换

       对于正数,原码和反码,补码都是一样的,都是正数本身。

       对于负数,原码是符号位为1,数值部分取X绝对值的二进制。

       反码是符号位为1,其它位是原码取反。

       补码是符号位为1,其它位是原码取反,未位加1。也就是说,负数的补码是其反码未位加1。

       示例:short a=130

      由于是正数,所以其原码,反码,补码都一样,因为是short类型,所以长度为16位,所以二进制码就是:0000 0000 1000 0010。

      如果是-130的话,其原码是符号位(1)加其绝对值的二进制,所以为10000000 1000 0010,其反码是原码除符号位其它位取反:11111111 0111 1101,补码就是反码末位加1,则补码是:1111 1111 0111 1110。再次重申,计算机中所有的二进制数都是按补码的形式进行运算和存储的,之所以我们经常意识不到补码,是因为经常计算的是正数,原码=反码=补码。

三.Byte范围

    (1byte为一字节8位,最高位是符号位,即最大值是01111111,因正数的补码是其本身,即此正数为01111111十进制表示形式为127。

    (2)最大正数是01111111,那么最小负是10000000(最大的负数是11111111,即-1)。

    (3)10000000是最小负数的补码表示形式,我们把补码计算步骤倒过来就即可。10000000减1得01111111然后取反10000000,因为负数的补码是其绝对值取反,即10000000为最小负数的绝对值,而10000000的十进制表示是128,所以最小负数是-128。

    (4)由此可以得出byte的取值范围是-128到+127

四.转换示例

   byte a=(byte)-130;

   System.out.println(a);

   请问a=?

   首先-130的原码在上面已经表示过了:1000 0000 1000 0010(假设是short类型),int类型的话同理,只是多增加16位二进制,然后符号位置为1。因为在计算机中任何二进制数都是用补码表示的,所以-130的补码是1111 1111 0111 1110,由于byte类型只有8位,所以将最后8位放入byte中,所以byte a的补码就是0111 1110,由此可以看出这个数是正数,则补码=原码,于是直接计算(2+4+8+16+32+64)=126。所以此时输出值为126。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值