轉載請註明原創出處,謝謝!java
以前在JVM菜鳥進階高手之路十(基礎知識開場白)的時候簡單提到了二進制相關問題,最近在看RocketMQ的源碼的時候,發現涉及二進制的內容蠻多,jdk源碼裏面也是有不少涉及到二進制相關的操做,今天這篇文章僅僅是掃盲篇,後續會介紹靈活運用篇。編碼
任何東西都有規範,提到JAVA就會提到2個規範,JAVA語言規範、JVM規範。JAVA語言規範主要定義JAVA的語法、變量、類型、文法等等,JVM規範主要定義Class文件類型、運行時數據、幀棧、虛擬機的啓動、虛擬機的指令集等等。spa
JAVA八種基本數據類型: 整形:byte,short,int,long 浮點型:float,double 布爾型:boolean 字符型:char3d
數據類型 | 所佔位數 |
---|---|
int | 32bit |
short | 16bit |
long | 64bit |
byte | 8bit |
char | 16bit |
float | 32bit |
double | 64bit |
boolean | 1bit |
**備註:**1字節=8位(1 byte = 8bit)code
**備註:**補碼的好處:cdn
- 使用補碼能夠沒有任何歧義的表示0。
- 補碼能夠很好的參與二進制的運算,補碼相加符號位參與運算,這樣就簡單不少了。
在上圖中,咱們瞭解到Float與Double都是支持IEEE 754對象
咱們以float來講明:blog
IEEE754單精度浮點格式共32位,包含三個構成字段:23位小數f,8位偏置指數e,1位符號s。將這些字段連續存放在一個32位字裏,並對其進行編碼。其中0:22位包含23位的小數f; 23:30位包含8位指數e;第31位包含符號s。內存
一個實數V在IEEE 754標準中能夠用V=(-1)s×M×2E 的形式表示,說明以下:ci
符號位 | 指數位 | 小數位 |
---|---|---|
1位 | 8位 | 23位 |
例如根據IEEE754,計算11000001000100000000000000000000的單精度浮點的值。
解題:
1 | 10000010 | 00100000000000000000000 |
---|---|---|
符號位 | 指數 | 尾數因爲指數不是所有爲0 因此小數位附加1 |
1 | 10000010 | **1.**00100000000000000000000 |
-1 | 2^(130-127) | (2^0 + 2^-3) |
結論: -1 * (2^0 + 2^-3) * 2^(130-127) =-9
一樣,你也能夠驗證一下十進制浮點數0.1的二進制形式是否正確,你會發現,0.1不能表示爲有限個二進制位,所以在內存中的表示是舍入(rounding)之後的結果,即 0x3dcccccd, 十進制爲0.100000001, 偏差0.000000001由此產生了。
說到這裏JVM菜鳥進階高手之路十(基礎知識開場白)的有些問題其實都解答了,因此涉及到錢的小數類型必須使用BigDecimal,禁止使用float和double。
咱們經常使用的進制有二進制、八進制、十進制和十六進制,十進制是最主要的表達形式。
二進制是0和1;八進制是0-7;十進制是0-9;十六進制是0-9+A-F(大小寫都可)。
兩位全爲1,結果才爲1:
0&0=0;
0&1=0;
1&0=0;
1&1=1;
複製代碼
用法:
例如:設X=1010 1110,取X的低4位,用X & 0000 1111 = 0000 1110 就能夠獲得。
只要有一個爲1,結果就爲1:
0|0=0;
0|1=1;
1|0=1;
1|1=1;
複製代碼
**用法:**經常使用來對一個數據的某些位置1;找到一個數,對應X要置1的位,該數的對應位爲1,其他位爲零。此數與X相或可以使X中的某些位置1。
例如:將X=1010 0000 的低四位置1,用X | 0000 1111 =1010 1111 就能夠獲得。
**兩個相應位爲「異」(值不一樣),則該位結果爲1,不然爲0: **
0^0=0;
0^1=1;
1^0=1;
1^1=0;
複製代碼
用法:
對於一個二進制數按位取反,即將0變1,1變0: ~1=0; ~0=1;
將一個數的各二進制位所有右移若干位,正數左補0,負數左補1,右邊丟棄。操做數每右移一位,至關於該數除以2.
左補0 or 補1 得看被移數是正仍是負。 例:4 >> 2 = 1 例:-14(1111 0010) >> 2 = -4 (1111 1100 )
各個位向右移指定的位數。右移後左邊突出的位用零來填充。移出右邊的位被丟棄 各個位向右移指定的位數。右移後左邊突出的位用零來填充。移出右邊的位被丟棄 例如: -14>>>2
即-14(1111 1111 1111 1111 1111 1111 1111 0010)>>> 2 =(0011 1111 1111 1111 1111 1111 1111 1100) = 1073741820
int a = 1120429670;
for (int i = 0; i < 32; i++) {
int t = (a & 0x80000000 >>> i) >>> (31 - i);
System.out.print(t);
}
複製代碼
說明:
- 0x80000000是數的十六進制表示,轉成二進制表示爲10000000000000000000000000000000
- 運算的優先級,移位運算高於邏輯運算,>>>高於&
- 位邏輯與運算 1&1 = 1 ,0&1 = 0
>>>
無符號右移,移出部分捨棄,左邊位補0;
若是讀完以爲有收穫的話,歡迎點贊、關注、加公衆號【匠心零度】。
我的公衆號,歡迎關注,查閱更多精彩歷史!!!