Java教程

小白的编程经验(原码、反码、补码以及位运算符)

本文主要是介绍小白的编程经验(原码、反码、补码以及位运算符),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

很多编程初学者都可能有一个误区,数据在计算机中存储的数据都是以二进制的形式,比如-2的二进制1000 0010。这句话看似没有问题,但是他们认为的二进制实际上是数据的原码,事实上计算机中存储的数据是以补码形式存储的。

这里就需要引入原码、反码和补码的概念。

原码、反码、补码

原码:数据的二进制,直接计算的结果。
如:10(0000 1010) -10(1000 1010)

反码:顾名思义原码取反,但需要分类讨论。正数的反码就是原码,负数的反码是原码除符号位外,其他位按位求反。
如:10(0000 1010) -10(11110101)

补码:所有数据在内存中都是以补码形式存储,也需要分类讨论。正数的补码就是原码,负数的补码是反码+1,但不能改变符号位(-128)。
如:10(0000 1010) -10(11110110)

注意:负数是指有符号数,无符号数均为非负数,原码即是补码。

补码的计算

1)第一种方法

先判断是正数还是负数,正数的补码就是原码。
如果是负数,根据原码、反码、补码的关系,一步步求出补码。

  1. 求原码,转换成二进制
  2. 求反码,原码除符号位不动,其他按位求反
  3. 反码+1得到补码

同理,可以从补码计算出原码。同样的先判断正负,正数的原码就是补码。
负数的原码跟着步骤倒着求即可。

  1. 补码-1得到反码
  2. 反码符号位不变,其他位按位求反
  3. 原码转十进制

2)第二种方法

同样的,先判断是正数还是负数,正数的补码就是原码。
而负数的补码是通过 模减去负数的绝对值,将这个数转换成二进制即为补码。

这里引入一下模的概念,“模”是指一个计量系统的计数范围,如:时钟的计量范围是0~11,模=12。表示n位的计算机计量范围是 0-2的n次幂-1,模=2的n次幂.“模”实质上是计量器产生“溢出”的量,它的值在计量器上表示不出来,计量器上只能表示出模的余数。

		[X]补 = 模-| X |
		
		按照定义,-128,如下求补码。
		
		[-128]补 = 256-|-128| = 128
		
		写成二进制,就是:1000 0000。

反码的出现

在计算机中只有加法没有减法,1-1 其实是 1+(-1)。如果用原码计算1+(-1)计算出的结果等于-2,与实际情况不同。因此反码出现了,反码的出现就是为了解决1+(-1)这类问题的。

原码计算 1+(-1)

  		 1 		0000 0001
  	+	-1		1000 0001
  -------------------------------
  				1000 0010    =>  -2

反码计算 1+(-1)

  		 1 		0000 0001
  	+	-1		1111 1110
  -------------------------------
  				1111 1111     =>   反码
  				1000 0000     =>   结果是-0,负数的原码是反码除符号位各位取反

补码的出现

反码的出现解决了1+(-1)的问题,尽管结果没问题,但是出现了-0这个数,也就是0这个数占了两个二进制(+0和-0),因此出现了补码来解决这个问题。

补码计算 1+(-1)

  		 1 		0000 0001
  	+	-1		1111 1111
  -------------------------------
  				0000 0000     =>   补码
  				0000 0000     =>   结果是+0,正数的反码是补码
  				0000 0000     =>   结果是+0,正数的原码是反码

补码的出现解决了-0的问题,使得-0的位置空了出来,于是约定 -0 = -128

位运算符

位运算符(将数据转换成二进制补码,对每一位二进制运算):& | ~ ^ >> <<

A & B 按位相与

    10101101      0xAD 
&   01101110      0x6E
-------------
    00101100      0x2C

A | B 按位相或

    10101101      0xAD 
|   01101110      0x6E
-------------
    11101111      0xEF

~A 按位求反

   ~ 10101101     0xAD
   -----------
     01010010     0x52

A ^ B 按位异或,相同为0,不同为1

        10101101      0xAD 
    &   01101110      0x6E
     -------------
        11000011      0xC3

A << n 把A的补码向左移动n位,左边超出范围丢弃,右边补零 (相当于乘上2^n倍)

    10101101 << 4     0xAD
    --------------
    11010000          0xD0

A >> n 把A的补码向右移动n位, 右边丢弃,左边补符号位

	10101101 >> 4     0xAD
    --------------
    00001010          0xA

结语

希望这篇文章对你有所帮助

这篇关于小白的编程经验(原码、反码、补码以及位运算符)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!