位运算的基础知识(原码、反码、补码等)

目录

一、原码

二、反码

三、补码

四、浮点数

五、位运算(&   |   ~  ^  <<   >>)

   一、& 与运算

  二、| 或运算

  三、~ 逐位取反(符号位除外)

  四、^ 异或运算

五、<<  左移运算

六、 >> 右移运算

 七、>>>  无符号右移

六、位运算应用


今天看到一个算法题,其中有一个解法是通过位运算来提高效率的。然后写这篇博客来回忆与总结以下位运算的知识

一、原码

原码(true form)是一种计算机中对数字二进制定点表示方法。原码表示法在数值前面增加了一位符号位(即最高位为符号位):正数该位为0,负数该位为1(0有两种表示:+0和-0),其余位表示数值的大小。                                                      ----百度百科

例如:11的原码为00001011 ,-11的原码为10001011,其中一位符号位,七位数据位。

   代码实现(整数部分):  

public static void bytedata(int byte_length,int data)//其中byte_length代表着几位
  {    Stack<Integer >stack=new Stack<>();//存储数据
        boolean Negative=false;
         if(data<0)//如果是负数那么就标记,并且将其转化为负数
         { data=Math.abs(data);
            Negative=true;
         }
	  while(data!=0)//不断除2
	  {  
		   stack.push(data%2);
		  data=data/2;
	  }
	  int middle_size=stack.size();
	  for(int i=middle_size+1;i<=byte_length-1;i++)//保留一位变成符号位
	  {  stack.push(0);
	  }
	  if(Negative)
	  stack.push(1);
	  else 
		  stack.push(0);
	  System.out.print("二进制数据为:");
	  while(!stack.isEmpty())
		 System.out.print(stack.pop());
  }
   public static void main(String args[])
	 {
		bytedata(8,4);//8位数据表示,4代表值
	 }

      实现结果:

      代码实现(小数部分):

  //小数部分处理
  public static void float_data(float data)
  {  ArrayList<Integer> arrayList=new ArrayList<>();
	   boolean Negative=false;
	   int j=0;
	   if(data<0)
	   {
		   data=Math.abs(data);
		   Negative=true;
	   } 
	  while(Math.abs(data-0.0)>0.000001)
	   {   data=(data*2);
	   if(data>1)
	   {
		   arrayList.add(1);
		   data=data-1;
	   }
	   else if(data<1)
		   arrayList.add(0);
	   else 
	   {   arrayList.add(1);
		   break;
	   }
	   }
	  if(Negative)
		  System.out.print("-0.");
	  for (int i = 0; i < arrayList.size(); i++) {
		System.out.print(arrayList.get(i));
		
	}
  }

    运行结果:

   

二、反码

    就是原码按位取反,注意符号位不动(对于负数而言,正数的原码=反码=补码)

三、补码

     就是反码+1,计算机中负数用补码存储(正数的原码=反码=补码)。

四、浮点数

在计算机中浮点数一般以IEEE754的形式保存。

即单精度浮点数字长32位,尾数长度23,指数长度8,指数偏移量127;

双精度浮点数字长64位,尾数长度52,指数长度11,指数偏移量1023;

 例如:   178.0625的IEEE754形式表示过程如下

          整数部分178 二进制形式为10110010

          小数部分  二进制为0001

          整体形式为 10110010.0001  将其标准化为1.01100100001*2^7 

         那么移码变为7+127=134(二进制形式为10110010)

        最终格式变为了0 10110010  01100100001000000000000

                           (想到了当初考研的情形(>!<))    

五、位运算(&   |   ~  ^  <<   >>)

位运算规则
名称 规则
& 与运算  二者全为1则为1,其余为0       (与  相当于两者同时成立)
|   或运算 二者之间有1则为1,其余为0   (或 相当于两者有一个成立即可)
~   按位取反 除符号位外逐位取反 。
 ^  异或运算 两者相同为0,不同为1  (异或  异代表不同的意思)
<<  左移运算 左移,移掉的省略,右边补零。 相当于*2
>>  右移运算 右移,移掉的省略,正数左边补0,负数左边补1。相当于/2
>>> 无符号右移 将二进制数按指定右移几位,移掉的省略,左边缺失的位,用0补齐

   一、& 与运算

         x&0=0

         x&(-1)=x  (因为 -1对应为11111111)

        x&x=x

  二、| 或运算

     x|(-1)  =-1  (因为-1对应的为11111111,那么逐位或下来肯定为1111111,代表着-1)

    x|x  =x 

  三、~ 逐位取反(符号位除外)

  ~(-1)=0  (因为-1对应的为11111111,那么逐位取反下来为100000,代表着0)

  四、^ 异或运算

   x^x=0

  x^0=x

  x^(~x)=-1  (因为~x 中 原来的1变为0,那么与x中的值不同,产生1)

(记住任何数异或自己都为0;任何数异0都为本身;进行异或的数可以无序交换)

五、<<  左移运算

相当于*2     例如 5<<3 5x2³=40

六、 >> 右移运算

  相当于 /2   例如 -70>>2 -70÷2²=-18

 七、>>>  无符号右移

 l例如    -1>>>1   =2的31次方-1

六、位运算应用

      一、判断奇偶(奇数二进制最后一位为1,偶数为0)

	if((x&1)==0)
		{
			System.out.println("为偶数");
		}
		else 
			System.out.println("为奇数");

          二、交换两个数

void swap(a,b){
       a^=b;
       b^=a;
       a^=b;
}

             计算过程(看的别人的):

a=a^b
b=b^a=b^(a^b)=(b^b)^a=a  --> b=a
a=a^b=(a^b)^b^(a^b)=(a^a)^(b^b)^b=b   --> a=b

           三、判断正负(向右移31位获取到符号位)

int b = a>>31 ,b=0则为正,b=1则为负

        四、  取相反数:
            a的相反数 ~a+1

      五、取反

     ~n=-(n+1)

      六、获取整数n的二进制串中最后一个1

          -n&n=~(n-1)&n

      七、去除整数n的二进制串中最后一个1

           n&(n-1)

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章