Java基礎系列-二進制操做

原創文章,轉載請標註出處:《Java基礎系列-二進制操做》java

概述

Java源碼中涉及到大量的二進制操做,很是的複雜,但很是的快速。佈局

Java二進制表示法

首先了解下二進制,二進制是相對十進制而言的,固然還有八進制,十六進制等等,咱們經常使用的都是十進制,計算機用的都是二進制,而符號表示經常使用十六進制。code

二進制就是隻有0、1兩個值表示的數,規則是逢二進一。ci

整數表示法

Java中使用補碼來表示負數,具體就是除符號位以外,剩餘位取反加1,符號位不變仍是1(符號位0-正數,1-負數)字符串

Java中二進制符號位也不是固定的,在Byte類型的數值中,因爲其爲一個字節即八位取值範圍爲-128到127,其符號位就是第8位二進制位。
以下所示:get

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位爲符號位。it

浮點數表示法

Java中的浮點數大多數都沒法精確表示,爲何呢?由於使用二進制來表示小數同樣存在和十進制表示小數同樣的問題,存在無限循環的小數和無限不循環的小數,好比十進制的1/3,十進制爲0.333...無限個3,二進制表示一樣會有這個問題,二進制表示0.一、0.二、0.三、0.4等都不能精確表示,0.5能夠表示爲2^(-1),能夠精確表示,可見只有能夠精確的使用科學計數法表示的二進制小數才能精確表示,其餘的一概沒法精確表示。class

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);// 將長整型數的佈局解析爲一個雙精度浮點數
    }
}
相關文章
相關標籤/搜索