小數(shù)二進制的轉(zhuǎn)換和浮點數(shù)的存儲是兩個不太相關(guān)的內(nèi)容泄私,所以本文分兩個主題分別記錄午绳。
進制轉(zhuǎn)換
十進制整數(shù)轉(zhuǎn)二進制
除二取余法嗜憔,余數(shù)倒排杜跷。
原理來源于:
十進制:
二進制:
反向求解的時候就是除2(基數(shù))取余涣旨。
11 ÷ 2 = 5 余 1
5 ÷ 2 = 2 余 1
2 ÷ 2 = 1 余 0
1 ÷ 2 = 0 余 1
得到二進制:1011
十進制小數(shù)轉(zhuǎn)二進制
乘二取整歪架。
原理來源于:
十進制:
二進制:
反向求解的時候就是乘2(基數(shù))取整:
0.6825 * 2 = 1.375 拿走整數(shù)部分1,剩0.375
0.375 * 2 = 0.75 拿走整數(shù)部分0霹陡,剩0.75
0.75 * 2 = 1.5 拿走整數(shù)部分1和蚪,剩0.5
0.5 * 2 = 1 拿走整數(shù)部分1,剩0烹棉,結(jié)束
得到二進制:0.1011
通過上面的運算可以知道:11.6825轉(zhuǎn)成二進制是:1011.1011
另外一個規(guī)律:小數(shù)尾數(shù)為5(x.5攒霹、x.25、x.xxxxx5)才能用完整的二進制表示浆洗,不然一直乘2小數(shù)部分永遠不能為0催束。
快速運算:
0.1(二進制)=0.5(十進制)
0.01(二進制)=0.25(十進制)
0.001(二進制)=0.125(十進制)
……
小數(shù)存儲
我們假設(shè),小數(shù)點存儲在中間(定點數(shù))伏社,假設(shè)用8bit來存儲小數(shù):
1011 1011
就等于1011.1011抠刺。用16bit來存儲小數(shù):0000 1011 1011 0000
就等于1011.1011。
以上只是我們的假設(shè)摘昌,為了統(tǒng)一速妖,現(xiàn)在計算機都采用IEEE 754的標(biāo)準(zhǔn)來存儲小數(shù)(浮點數(shù))。有單精度(32bit)和雙精度(64bit)兩種聪黎。
統(tǒng)一公式:
其中s為符號位罕容,E為階碼,M為尾數(shù)。
s為所見即所得锦秒,0正數(shù)露泊,1負數(shù)。
E為移碼表示脂崔,移滤淳,相當(dāng)于加上,Bias稱偏移量砌左。
M為尾數(shù)脖咐,隱藏最高位1,相當(dāng)于計算尾數(shù)時汇歹,要加上1屁擅。
以0.4375為例,因為M尾數(shù)最高位要為1产弹,也就是我們要想辦法讓0.4375表示成的形式:
用單精度表示派歌,偏移量為:
現(xiàn)在的任務(wù)變成了將125和1.75(需要隱藏高位1,變成0.75)轉(zhuǎn)換成二進制:
痰哨、
所以0.4375的浮點數(shù)表示就是:
在線轉(zhuǎn)換網(wǎng)址
同理胶果,將 轉(zhuǎn)換成小數(shù)就是:
階數(shù):0111 1101 = 125,實際 125 - 127(偏移量) = -2
尾數(shù):1100 0000 0000 0000 000 = 0.11(二進制) = 0.5+0.25=0.75(十進制)
尾數(shù)補隱藏位1:1+0.75=1.75
原小數(shù):
雙精度浮點數(shù)的偏移量:
利用java轉(zhuǎn)換
long l = Double.doubleToLongBits(0.4375);
System.out.println(l);
// 11111111011100000000000000000000000000000000000000000000000000
System.out.println(Long.toBinaryString(l));
Long aLong = Long.valueOf("11111111011100000000000000000000000000000000000000000000000000", 2);
double v = Double.longBitsToDouble(aLong);
// 0.4375
System.out.println(v);