1. 程式人生 > >java中的資料儲存,位元組轉換,位操作

java中的資料儲存,位元組轉換,位操作

1. java中資料儲存是按照位元組儲存的,一個位元組是8位,也就是java中的byte資料型別,java中byte表示的是有符號數,第八位(從右至左)表示的是符號位,一個位元組表示的範圍是2^8,也就是256個數,表示的範圍是:-128到127,因為第八位始終是符號位,所以最大的正值就是0111 1111,也就是2^8 - 1, 在實際的資料儲存時,是按照補碼的形式儲存的,為什麼按照補碼形式?請先了解原碼,反碼,補碼:

首先統一按照2進位制格式也就是全是0和1組成的數,簡單來說:原碼:就是一樣的數。反碼:正數:正數的反碼與原碼相同。負數:負數的反碼,符號位為“1”,數值部分按位取反。補碼:正數補碼一樣,負數:除符號位外,按位取反,末尾加1。

接著說為什麼按照補碼形式儲存?

因為原碼和反碼錶示的範圍其實只有255個,衝突就在0這個地方,原碼中:理論上0000 0000 與1000 0000 表示的該是同一個數,因為+0和-0相等,這樣能儲存的數實際上就少了一個,也就是255個。反碼中:也是同樣的問題:0按照2進位制反碼錶示:0000 0000,然後神奇的發現1111 1111求出來的值同樣也是0,但是是-0,在實際運算中+0和-0明明就是一個數。而補碼的出現很好的解決了這個問題,也就是一個位元組可以表示256個數。

按照補碼的形式儲存時,正數就不多說了,全部都一樣只要不超出表示範圍就行,負數的話,舉個例子:如果儲存的是aa,也就是1010 1010,那麼按照計算機儲存的話輸出看一下:

為什麼是-86,來一步一步算一下就知道了:aa == 1010 1010,取補碼就是:先求反,1101 0101,再 + 1,1101 0110,再轉化成10進位制,注意第一位是符號位,那麼就是-(2^6 + 2^4 + 2^2 + 1) = -86。計算結束。

2.知道計算機是按照補碼形式儲存的話,那麼接下來繼續看,實際的專案過程中,我們需要的可能是並不是這個值本身,怎麼理解這句話呢?舉個例子來說,接著上面的例子我需要的是aa,並不是計算出來的-86,怎麼解決?因為java中全部按照補碼的形式儲存,可以把這個位元組通過位元組通過於運算,0xaa & 0x0ff,因為java中預設表示的數都是int型別,這樣0x0ff其實就是一個4個位元組的int型別的資料,這樣的話計算結果就是:

居然在cmd視窗下輸出還是-86,我換了下編譯器,程式碼如下:

這樣的話計算結果就對上了:2^7 + 2^6 + 2^4 + 2^2 + 2 = 170;

3.然而日在實際情況中有遇到的都沒有這麼easy,為了提高傳輸效率,對每個位元組都會有所限制,舉個例子來說:你傳遞的數只在0-255之間或者-127-128之間,那麼用一個byte就可以儲存一個資訊,如果你傳遞的數在-32768-32767之間或者0-65535之間,就可以用一個short儲存一個資訊,以此類推int long等,如果正常傳輸情況也可以這樣那該多好,但是真實情況並不是這樣,舉個例子來說:比如我需要的數的範圍是0-8191或者-4095-4096的時候,這就比較麻煩了,為什麼是連個範圍都可以?這裡說明一下,因為全部可以轉化為2進位制,所以這種情況就需要打破常規思維,比如我可以自己定義在傳輸的時候12這個數表示的實際數是8,也就是說這個數剛開始是8,在傳輸的時候是12,但是我解析的時候要把他再轉成8,當然這其實是不符合邏輯的,我只是舉了一個不恰當的例子。回到原來的問題,我需要的傳輸的數的範圍是-4095-4096,這樣的數的範圍其實只需要13個二進位制位就可以表示,計算一下:4096 - 4095 + 1 = 8192,這裡的1代表的是0,不能把0漏掉,8192=2^13,也就是說我可以用2個位元組表示一個數還綽綽有餘,多出來3個位元組可以表示其他的儲存資訊,比如這個數表示的是什麼資訊等等,這樣的話傳輸效率就明顯變高了,充分利用每一個位元組,為了便於理解,那麼就舉個形象點的例子:比如傳過來的數是0x3244,轉化成2進位制就是0011 0010 0100 0100,按照之前的假設,這樣的2個位元組傳輸過程中就可以使用後面的13個位元組表示實際的數,也就是1 0010 0100 0100,表示實際的數,符號位也可以自己通過一個位來定義,假設傳輸的是一個有符號數,第一位表示的是符號,那麼這裡就是一個負數,怎麼計算出他的真實值呢?

        實際情況中並不知道這是一個正數還是負數,所以先:0x3244 & 0x1000判斷結果是不是等於0,

        如果等於0, 表示符號位,也就是第13位是0,那麼接下來就可以0x3244 & 0x0fff轉化成一個12位的無符號數的位元組資料,然後 按照位元組補的方式相加兩個位元組資料,也就是第一個位元組((0x32 & 0x000f) <<8) + (0x44 & 0x00ff),這樣求出來的一個數是int4個位元組,因為java預設整數使用的都是int,當然如果你需要用一個short表示時也是可以的,只不過需要強制轉化,注意強制轉化,容易出錯,計算公式如下:(short)(((0x32 & 0x000f) << 8) | (0x44 & 0x00ff)),如果是轉化成short儘量使用|這個運算子。

        如果不等於0,表示符號位,也就是第13位是1,那麼接下來就可以(short)(((0x32 | 0x00f0) << 8) | (0x44 & 0x00ff))這樣的話得到就是一個負數,不加強轉的話得到的是一個正數,因為預設的是int,4個位元組,前面的16個位還是0,記得強制轉化。

       當然解析就這樣了,還多出來3個位,你可以儲存性別,或者任何3個位都可以儲存的內容了。