原創文章,轉載請標註出處: "《Java基礎系列 二進位操作》" 概述 Java源碼中涉及到大量的二進位操作,非常的複雜,但非常的快速。 Java二進位表示法 首先瞭解下二進位,二進位是相對十進位而言的,當然還有八進位,十六進位等等,我們常用的都是十進位,電腦用的都是二進位,而符號表示常用十六進位 ...
原創文章,轉載請標註出處:《Java基礎系列-二進位操作》
概述
Java源碼中涉及到大量的二進位操作,非常的複雜,但非常的快速。
Java二進位表示法
首先瞭解下二進位,二進位是相對十進位而言的,當然還有八進位,十六進位等等,我們常用的都是十進位,電腦用的都是二進位,而符號表示常用十六進位。
二進位就是只有0、1兩個值表示的數,規則是逢二進一。
整數表示法
Java中使用補碼來表示負數,具體就是除符號位之外,剩餘位取反加1,符號位不變還是1(符號位0-正數,1-負數)
Java中二進位符號位也不是固定的,在Byte類型的數值中,由於其為一個位元組即八位取值範圍為-128到127,其符號位就是第8位二進位位。
如下所示:
Byte型數據
1 -> 0000 0001
-1 -> 1111 1111(計算:1為00000001,-1為10000001,取反為11111110,加1為11111111)
127 -> 0111 1111
-127 -> 1000 0001(計算:127為01111111,-127為11111111,取反為10000000,加1為10000001)
-128 -> 1000 0000(計算:128為100000000,取8位為00000000,-128為10000000,取反為11111111,加1為10000000)
Short型數為兩個位元組16位數值,其符號位為第16位:
Short型數據
1 -> 0000 0000 0000 0001
-1 -> 1111 1111 1111 1111(計算:1為0000000000000001,-1為1000000000000001,取反為1111111111111110,加1為1111111111111111)
32767 -> 0111 1111 1111 1111
-32767 -> 1000 0000 0000 0001(計算:32767為0111111111111111,-32767為1111111111111111,取反為1000000000000000,加1為1000000000000001)
-32768 -> 1000 0000 0000 0000(計算:32768為10000000000000000,取16位為0000000000000000,-32768為1000000000000000,取反為1111111111111111,加1為1000000000000000)
Integer為32位,Long為64位,表示方式如上,Integer第32位為符號位,Long型第64位為符號位。
浮點數表示法
Java中的浮點數大多數都無法精確表示,為什麼呢?因為使用二進位來表示小數一樣存在和十進位表示小數一樣的問題,存在無限迴圈的小數和無限不迴圈的小數,比如十進位的1/3,十進位為0.333...無限個3,二進位表示同樣會有這個問題,二進位表示0.1、0.2、0.3、0.4等都不能精確表示,0.5可以表示為2^(-1),可以精確表示,可見只有可以精確的使用科學計數法表示的二進位小數才能精確表示,其他的一律無法精確表示。
Java中使用32位的float和64位的double表示浮點小數。
Float型浮點數
格式:1位符號位,8位指數,23位尾數(S1_E8_M23)
符號位:0-正數,1-負數
指數位:採用移位存儲,即用真實數值+127的二進位值來表示,比如,1要表示成128(即:10000000),128表示為255(即11111111)
尾數位:將十進位數轉化為二進位之後,轉化為科學計數法形式,取小數位作為尾數位,不足23位結尾補0
0.5 -> 0011 1111 0000 0000 0000 0000 0000 0000
(計算:0.5 = 1/2,即2^(-1),指數位為-1+127=126,即01111110,尾數為0,因為是正數,符號位為0)
10.5 -> 0100 0001 0010 1000 0000 0000 0000 0000
(計算:10的二進位為1010,0.5的二進位為0.1,所以10.5的二進位Wie1010.1,科學計數法表示為1.0101E11,如此一來,指數位為3+127=130,即10000010,符號位為0,尾數為0101,後面補0,夠23位)
35.3 -> 0100 0010 0000 1101 0011 0011 0011 0011
(計算:35的二進位為100011,0.3的為二進位為0.01001100110011001100110011001100110011...,合起來就是100011.0100110011001100110011...,科學計數法為1.00011010011001100110011...E101,如此一來,符號位為0,指數位為5+127=132,即10000100,尾數為00011010011001100110011)
Double型浮點數
格式:1位符號位,11位指數,52位尾數
符號位:0-正數,1-負數
指數位:採用移位存儲,用真是數值+1023的二進位值來表示,比如1要表示成1024(即:10000000000)
尾數位:將十進位轉化為二進位,再轉為科學計數法,取小數位作為尾數,不足52位結尾補0
35.3 -> 0100 0000 0100 0001 1010 0110 0110 0110 0110 0110 0110 0110 0110 0110 0110 0110
(計算:35的二進位為100011,0.3的為二進位為0.01001100110011001100110011001100110011...,合起來就是100011.0100110011001100110011...,科學計數法為1.00011010011001100110011...E101,如此一來,符號位為0,指數位為5+1023=1028,即10000000100,尾數為0001101001100110011001100110011001100110011001100110)
進位轉化:
十進位轉二進位,整數部分除以2,整除為0,否則為1,直到結果為1,然後從後竄到前的結果就是其二進位值
比如:10 10/2 = 5 整除 0 5/2 = 2 未整除 1 2/2 = 1 整除 0 1 結果為1,結束 1 最後10的二進位值為:1010 再比如77 77/2=38 未整除 1 38/2=19 整除 0 19/2=9 未整除 1 9/2=4 未整除 1 4/2=2 整除 0 2/2=1 整除 0 1 結果為1,結束 1 最後77的二進位為1001101
小數部分的二進位化,取小數部分乘以2,結果大於等於1,取1,否則取0,再取小數部分乘以2,取值,直到結果為0或者迴圈
比如:10.22 先進行整數部分二進位,結果為1010 再進行小數部分二進位: 0.22 * 2 = 0.44 0 0.44 * 2 = 0.88 0 0.88 * 2 = 1.76 1 0.76 * 2 = 1.52 1 0.52 * 2 = 1.04 1 0.04 * 2 = 0.08 0 0.08 * 2 = 0.16 0 0.16 * 2 = 0.32 0 0.32 * 2 = 0.64 0 0.64 * 2 = 1.28 1 0.28 * 2 = 0.56 0 0.56 * 2 = 1.12 1 0.12 * 2 = 0.24 0 0.24 * 2 = 0.48 0 0.48 * 2 = 0.96 0 0.96 * 2 = 1.92 1 0.92 * 2 = 1.84 1 0.84 * 2 = 1.68 1 0.68 * 2 = 1.36 1 0.36 * 2 = 0.72 0 0.72 * 2 = 1.44 1 ... 結果就是1010.00111000010100011110... 若是以科學計數法表示那就是1.01000111000010100011110...E11 若是表示成float的二進位形式那就是:0100 0001 0010 0011 1000 0101 0001 1110
Java二進位運算符
與:&
與操作規則:全1為1,否則為0
例如:
1010 & 0101 = 0000
1111 & 0000 = 0000
1010 & 1111 = 1010
0101 & 0000 = 0000
擴展:二進位中的1的與操作具有保留原值的效果,任何值(0,1)和1進行與操作結果都不會變。這一點在HashMap中得以使用。
或:|
或操作規則:有1為1,全0為0
例如:
1010 | 0101 = 1111
1111 | 0000 = 1111
1010 | 1111 = 1111
0101 | 0000 = 0101
擴展:二進位中的0的或操作也具有保留原值的效果,任何值(0,1)和0進行或操作結果都不會變。
非:~
非操作規則:0為1,1為0
例如:
~1111 = 0000
異或:^
異或操作規則:相同為0,不同為1
例如:
1010 ^ 0101 = 1111
1111 ^ 0000 = 1111
1010 ^ 1111 = 0101
0101 ^ 0000 = 0101
擴展:二進位中的0的異或操作具有保留原值的效果,1的異或操作具有取反的效果。
左移:<<
左移規則:符號位保持不變的情況下剩餘全部左移一位,低位補0,相當於乘以2的結果
例如:
0011 << 2 = 1100
1000 0000 1000 0001 << 2 = 1000 0010 0000 0100 (首位1為符號位)
右移:>>
右移規則:符號位保持不變的情況下剩餘全部右移一位,高位補0,相當於除以2的結果
例如:
0011 >> 2 = 0000
1000 0000 1000 0001 >> 2 = 1000 0000 0010 0000 (首位1為符號位)
無符號右移:>>>
無符號右移規則:全員右移一位,高位補0,相當於除以2的結果
例如:
1000 0000 1000 0001 >> 2 = 0010 0000 0010 0000 (首位1為符號位)
二進位操作
參考例子中的操作:
public class BinaryTest {
public static void main(String[] args){
int a = 100;
String as = Integer.toBinaryString(a);// 整數的二進位表示,可輸出二進位字元串
long b = 200;
String bs = Long.toBinaryString(b);// 長整數的二進位表示,可輸出二進位字元串
float c = 30.0f;
int ci = Float.floatToIntBits(c);// 將浮點數的二進位佈局解析為整型表示
int ci2 = Float.floatToRawIntBits(c);// 將浮點數的二進位佈局解析為整型表示
float f2 = Float.intBitsToFloat(a);// 將整型數的佈局解析為一個浮點數
double d = 302.22d;
Long dl = Double.doubleToLongBits(d);// 將浮點數的二進位佈局解析為長整型表示
Long dl2 = Double.doubleToRawLongBits(d);// 將浮點數的二進位佈局解析為長整型表示
double d2 = Double.longBitsToDouble(b);// 將長整型數的佈局解析為一個雙精度浮點數
}
}