位運算的基礎知識(原碼、反碼、補碼等)

目錄

一、原碼

二、反碼

三、補碼

四、浮點數

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

   一、& 與運算

  二、| 或運算

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

  四、^ 異或運算

五、<<  左移運算

六、 >> 右移運算

 七、>>>  無符號右移

六、位運算應用


今天看到一個算法題,其中有一個解法是通過位運算來提高效率的。然後寫這篇博客來回憶與總結以下位運算的知識

一、原碼

原碼(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)

 

 

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