1. 程式人生 > >為什麼在JAVA/JAVASCRIPT裡要做&0xFF位運算

為什麼在JAVA/JAVASCRIPT裡要做&0xFF位運算

function dataGet(byte:Byte):Number{
    return byte&0xFF;
}

為什麼要做&0xFF的位運算?

先看 原始碼  反碼  補碼,計算機內部儲存的二進位制碼是補碼。原碼最高位位符號位,0表示正數,1表示負數,除非變數特別宣告為unsigned型別則最高位就非符號而表示的是值(這個在JAVA/js裡沒有),計算機儲存器和編譯器之間具體怎麼去轉化unsigned這裡不討論,如果討論就扯遠了。一般我們討論的都是帶符號的二進位制碼,計算機內部儲存也是帶符號,只要帶符號,低位元組轉為高位元組,全部補1,切記!

  • 原碼就是符號位加上真值的絕對值, 即用第一位表示符號, 其餘位表示值。
  • 反碼的表示方法是:正數的反碼是其本身;負數的反碼是在其原碼的基礎上, 符號位不變,其餘各個位取反。
  • 補碼的表示方法是:正數的補碼就是其本身;負數的補碼是在其原碼的基礎上, 符號位不變, 其餘各位取反, 最後+1。 (即在反碼的基礎上+1)
  • 十進位制數 原碼 反碼 補碼
    85 0101 0101 0101 0101 0101 0101
    -85 1101 0101 1010 1010 1010 1011
    9 0000 1001 0000 1001 0000 1001
    -9 1000 1001 1111 0110 1111 0111

    要想將計算機中儲存的二進位制碼也就是補碼轉換成十進位制數,首先得轉換成原碼,然後再轉換成十進位制資料。負數的原始碼轉補碼和補碼轉原始碼是同樣的操作,除開符號位以外,其他位取反加1.再強調最高位為符號位。 

         現在來說為什麼JAVA/JS裡低位元組轉高位元組要做0xFF位運算了.上面提到了unsigned這個關鍵字,它的意思表示無符號。而一般變數只要沒有類似這unsigned特別標註的都是有符號的,那麼有符號的變數在低位元組轉高位元組時高位預設全部高位補1

         有了上面的基礎,那麼就說說為什麼要做&0xFF了: 

//以上面9和-9為例子 ,這裡Byte暫時表示位元型別一個位元組,Number型別暫時代表4個位元組
1.  varableByte:Byte = 9; //一個位元組儲存9
2.  varableNumber:Number = varableByte&0xFF;

//這裡為什麼不用&0xFF
3.  varableByte:Byte = -9; //一個位元組儲存9
4.  varableNumber:Number = varableByte;




當varableByte為正數9時,我做了&0xFF,當varableByte為負數-9時我卻沒做位運算。原因就是低位元組轉高位元組高位補1,

如果編譯器是原碼做位運算:

9: 原碼 00001001    轉換成number型別後高位補1: 11111111 11111111 11111111 00001001 (請問這個的十進位制值還是9嗎) ,那麼我趕緊補救做位運算,&0xFF的二進位制補碼00000000 00000000 00000000 11111111 ,運算後得到:

00000000 00000000 00000000 00001001,這個在Number型別下的二進位制補碼和原始碼正是十進位制數9,這樣就保持了值不變。

-9:原碼 10001001    轉換成number型別後高位補1: 11111111 11111111 11111111  10001001,這個做&0xFF後,

00000000 00000000 00000000 10001001,還好是-9。但我擔心編譯器用下面補碼做位運算。

如果編譯器是補碼做位運算:

9: 補碼 00001001    轉換成number型別後高位補1: 11111111 11111111 11111111 00001001 (請問這個的十進位制值還是9嗎) ,那麼我趕緊補救做位運算,&0xFF的二進位制補碼00000000 00000000 00000000 11111111 ,運算後得到:

00000000 00000000 00000000 00001001,這個在Number型別下的二進位制補碼和原始碼正是十進位制數9,這樣就保持了值不變。

-9:補碼 11110111    轉換成number型別後高位補1: 11111111 11111111 11111111  11110111,這個做&0xFF後,00000000 00000000 00000000 11110111,這十進位制數還是原來的-9嗎,變成正數了,哎相當無語。

混亂的問題來了:

   1.0xFF的二進位制碼為什麼前面補的是0?去問你的編譯器,貌似常量的16進位制資料轉換成二進位制後前面預設補0,估計也不一定,還是要根據自己編譯器去發現,真的是無語!

         2.我們做位運算後,編譯器解析的是原碼還是補碼作運算呢?去問編譯器吧。實驗兩次就是知道了,也許各編譯器有差異,也許都是統一標準。還是讓人無語!!

結語: 至少知道了為什麼要&0xFF了,主要是因為在非unsigned的情況下正數在 低位轉高位 值會變,為了避免值發生變化,我們才&0xFF,而如果是負數,就必須要弄清楚當前編譯器是原碼還是補碼做位運算了,原碼運算不變,補碼運算會變