java二進制操做計算的總結

寫在前面

一直以來對二進制的操做計算不太清楚,此次找了一些資料完整地進行了一些總結。html


1、進制類別和關係:

  1. 二進制,十進制,十六進制的區別和進制之間的相互轉換方法(概念性的東西,能夠百度)。
  2. n位的二進制可以表示2的n次方個數,如4位的二進制能夠表示十進制的0~15共16個數 。
  3. 十六進制的基數是16,數碼爲0、一、二、三、四、五、六、七、八、九、A、B、C、D、E、F,其中用A,B,C,D,E,F(字母不區分大小寫)這六個字母來分別表示10,11,12,13,14,15。
  4. 因爲十六進制的基數是2的冪,所以二進制和十六進制的轉換很方便。一個二進制數,只要把它從低位到高位每4位組成一組,4個二進制位能夠表示從0到15的數字,這恰好是1個16進制位能夠表示的數據,也就是說,將二進制轉換成十六進制只要每4位進行轉換就能夠了。
    • 0011 0101 1011 1111 = 0x35BF(以0x開始的數據表示16進制) 。
    • MIN_VALUE = 0x80000000對應的二進制是10000000 00000000 00000000 00000000
    • MAX_VALUE = 0x7fffffff對應的二進制是01111111 11111111 11111111 11111111

2、移位操做

  1. 左移位<< :
/* 00000001 << 1 = 00000010 */
    1 << 1 == 2 
/* 00000001 << 3 = 00001000 */
    1 << 3 == 8
複製代碼
  1. 右移位>> :
    向右移位是有符號操做符。和許多語言同樣,Java使用最高位來表示數值的正負,負數的最高位永遠爲1。一個以1開頭的二進制數移位後還將以1開頭,一個以0開頭的二進制數移位後還將以0開頭。
/* 11111111 11111111 11111111 11110000 >> 4 = 11111111 11111111 11111111 11111111 */
    0xFFFFFFF0 >> 4 == 0xFFFFFFFF 
	 
/* 00001111 11111111 11111111 11111111 >> 4 = 00000000 11111111 11111111 11111111 */
    0x0FFFFFFF >> 4 == 0x00FFFFFF
複製代碼
  1. 無符號右移>>> :這種移位會忽略符號位並老是用「0」來填充。
/* 10000000 00000000 00000000 00000000 >>> 1 = 01000000 00000000 00000000 00000000 */
    0x80000000 >>> 1 == 0x40000000
複製代碼
  1. 移位的做用
  • 迅速求2的冪。1向左移位1位是2,移2位是4,移3位是8…… 類似的,向右移1位至關因而把該數除以2。(將一個數k移動n位,能夠看作將k*2^n)
  • 建立掩碼。位掩碼可用於屏蔽或者修改一個二進制數中的某些指定位。如獲得00001000的掩碼能夠經過1 << 3獲得。

3、位運算操做符

  1. ~ :按位取反,若是位爲0,結果是1,若是位爲1,結果是0
~1111 == 0000
    ~0011 == 1100
複製代碼
  1. & : 按位與,兩個操做數中位都爲1,結果才爲1,不然結果爲0
1010 & 0101 == 0000
    1100 & 0110 == 0100
複製代碼
  1. ^ : 按位異或,兩個操做數的位中,相同則結果爲0,不一樣則結果爲1
1010 ^ 0101 == 1111
    1100 ^ 0110 == 1010
複製代碼
  1. | : 按位或,兩個位只要有一個爲1,那麼結果就是1,不然就爲0
1010 | 0101 == 1111
    1100 | 0110 == 1110
複製代碼
  1. 位運算符的做用:
  • 能夠選擇性的把一個二進制數的某位設爲0,讓數與一個全1可是某位爲0的數相與。如,01010101 & ~(1<<2) == 01010101 & 11111011 == 01010001

4、原碼, 反碼, 補碼:

對於一個數, 計算機要使用必定的編碼方式進行存儲。原碼,反碼,補碼是機器存儲一個具體數字的編碼方式。java

  1. 機器數和真值
    • 機器數:一個數在計算機中的二進制表示形式,叫作這個數的機器數。機器數是帶符號的,在計算機用一個數的最高位存放符號, 正數爲0, 負數爲1。如,00000011 和 10000011這兩個機器數分別表示+3和-3。
    • 真值:將帶符號位的機器數對應的真正數值稱爲機器數的真值。如,10000011其最高位 1 表明負,其真正數值是 -3而不是形式值131(10000011轉換成十進制等於131)。
  2. 原碼:符號位加上真值的絕對值, 即用第一位表示符號, 其他位表示值.如,[+1]原 = 0000 0001,[-1]原 = 1000 0001
    • 由於第一位是符號位, 因此 8 位二進制數的取值範圍是:[1111 1111 , 0111 1111] 即 [-127 , 127]
    • 原碼是人腦最容易理解和計算的表示方式.
  3. 反碼:正數的反碼是其自己,負數的反碼是在其原碼的基礎上,符號位不變,其他各個位取反。如,[+1] = [00000001]原 = [00000001]反 / [-1] = [10000001]原 =[11111110]反
    • 若是一個反碼錶示的是負數,人腦沒法直觀的看出來它的數值.一般要將其轉換成原碼再計算.
  4. 補碼:正數的補碼就是其自己,負數的補碼是在其原碼的基礎上,符號位不變,其他各位取反, 最後 +1. (即在反碼的基礎上 +1)
    • 對於負數, 補碼錶示方式也是人腦沒法直觀看出其數值的。一般也須要轉換成原碼再計算其數值。
  5. 爲什麼要使用反碼和補碼
    • 設計簡單:由於人腦能夠知道第一位是符號位,在計算的時候咱們會根據符號位,選擇對真值區域的加減。可是對於計算機,加減乘數是最基礎的運算,要設計地儘可能簡單。而讓計算機辨別"符號位"會讓計算機的基礎電路設計變得十分複雜。
    • 加法設計:能夠用符號位參與運算來簡化設計。根據運算法則減去一個正數等於加上一個負數, 即: 1-1=1+(-1)=0,因此機器能夠只有加法而沒有減法,這樣計算機運算的設計就更簡單了。
    • 原碼直接符號位相加,獲得的結果是錯誤的,所以須要使用反碼和補碼
  6. 反碼加法:
    反碼加法結果的真值部分是正確的,可是在"0"這個特殊的數值上,雖然人們理解上 + 0和 -0 是同樣的, 可是 0 帶符號是沒有任何意義的, 並且會有 [0000 0000]原和[1000 0000]原兩個編碼表示 0。
// 計算十進制的表達式: 1 - 1 = 0
    1 - 1 = 1 + (-1) = [0000 0001]原 + [1000 0001]原= [0000 0001]反 + [1111 1110]反 = [1111 1111]反 = [1000 0000]原 = -0
複製代碼
  1. 補碼加法:
1-1 = 1 + (-1) = [0000 0001]原 + [1000 0001]原 = [0000 0001]補 + [1111 1111]補 = [0000 0000]補=[0000 0000]原
複製代碼
  • 這樣 0 用 [0000 0000] 表示,而反碼出現問題的-0則不存在了,並且能夠用多餘的[1000 0000] 表示 -128:
(-1) + (-127) = [1000 0001]原 + [1111 1111]原 = [1111 1111]補 + [1000 0001]補 = [1000 0000]補
複製代碼
  • 在用補碼運算的結果中,[10000000]補就是-128,可是注意由於其實是使用之前的-0的補碼來表示 -128, 因此 -128並無原碼和反碼錶示(對-128的補碼錶示[10000000]補算出來的原碼是[0000 0000], 這是不正確的)
  • 使用補碼運算可以多表示一個最低數,這就是爲何8位二進制,使用原碼或反碼錶示的範圍爲 [-127, +127], 而使用補碼錶示的範圍爲 [-128, 127]。

5、Integer的MIN_VALUE和MAX_VALUE

  1. 計算機存儲數字是使用補碼, 因此對於編程中經常使用到的 32 位int類型,能夠表示範圍是: [-2^31, 2^31-1] 由於第一位表示的是符號位,而使用補碼錶示時又能夠多保存一個最小值。
  2. 從表示的數字總數來講,仍是 2^31*2(由於正負值,因此*2)
    • 對於正數的2^31來講,[00000000 00000000 00000000 00000000]表示了0,因此正數的最大值是2^31-1(由於一種排列一個數,數與數之間都是隔1,因此正數總數-1即正數的最大值)。
    • 對於負數的2^31來講,[10000000 00000000 00000000 00000000]表示了最大值,因此負數的最大值是-2^31,多表示了一個數。
  3. Integer.MAX_VALUE,即2^31-1=2147483647,最小值爲-2^31=Integer.MIN_VALUE -2147483648
  4. 越界問題
  • Integer.MIN_VALUE-1 = Integer.MAX_VALUE:
Integer.MIN\_VALUE - 1 = Integer.MIN_VALUE + (-1)
    
    10000000000000000000000000000000
+   11111111111111111111111111111111[補]
---------------------------------------------------
    1,01111111111111111111111111111111[補]
    捨棄最高位的進位,因此獲得的就是Integer.MAX_VALUE
複製代碼
  • Integer.MAX_VALUE + 1= Integer.MIN_VALUE:
    對Integer.MAX_VALUE加1,2147483648(越界了),結果是-2147483648,便是Integer.MIN_VALUE。
01111111111111111111111111111111
    +   00000000000000000000000000000001[正數補碼等於自己]
---------------------------------------------------
        10000000000000000000000000000000[補]
複製代碼
  • 對Integer.MIN_VALUE取絕對值:
    由於值爲-2147483648,絕對值2147483648超過Integer.MAX_VALUE 2147483647,因此值仍是Integer.MIN_VALU。由於,Integer.MAX_VALUE=01111111111111111111111111111111,再加1爲10000000000000000000000000000000,等於Integer.MIN_VALUE

4、Java中的方法

  • java代碼裏操做二進制數字的方法是使用Integer.parseInt()方法。如,Integer.parseInt(「101″,2)表明着把二進制數101轉換爲十進制數5。

5、參考資料

文章一文章二文章三文章四文章五算法

相關文章
相關標籤/搜索