關於Java中的IEEE765浮點數標記法

來源:互聯網
上載者:User

淩宇 在www.360doc.com中轉帖【IEEE浮點數標記法】,經過仔細研究,終於有點心得了。

float轉十六進位:

16進位浮點數的表示方法,根據IEEE的標準,分為32位和64位兩種,參數分別如下:

  符號位 指數位 指數位移量 尾數位
32位 1[31] 8[23-30] 23[0-22] 127
64位 1[63] 11[52-62] 52[0-51] 1023

 float
共計32位,摺合4位元組
由最高到最低位分別是第31、30、29、……、0位
31位是符號位,1表示該數為負,0反之。
30-23位,一共8位是指數位。
22-0位,一共23位是尾數位。

現在讓我們按照IEEE浮點數標記法,一步步的將float型浮點數123456.0f轉換為十六進位代碼。

在處理這種不帶小數的浮點數時,直接將整數部轉化為二進位表示:1 11100010 01000000。

也可以這樣表示:11110001001000000.0。

然後將小數點向左移,一直移到離最高位只有1位,就是最高位的1:1.11100010010000000。

一共移動了16位,在布耳運算中小數點每向左移一位就等於在以2為底的科學計演算法表示中指數+1,所以原數就等於這樣:1.11100010010000000 * ( 2 ^ 16 )。

好了,現在我們要的尾數和指數都出來了。顯而易見,最高位永遠是1,因為你不可能把買了16個雞蛋說成是買了0016個雞蛋吧?所以這個1我們還有必要保留他嗎?好的,我們刪掉他。

這樣尾數的二進位就變成了:11100010010000000最後在尾數的後面補0,一直到補夠23位:11100010010000000000000。

再回來看指數,一共8位,可以表示範圍是0 - 255的不帶正負號的整數,也可以表示-128 - 127的有符號整數。

但因為指數是可以為負的,所以為了統一把十進位的整數化為二進位時,都先加上127,在這裡,我們的16加上127後就變成了143,二進位表示為:10001111。
12345.0f這個數是正的,所以符號位是0,那麼我們按照前面講的格式把它拼起來:
0 10001111 11100010010000000000000
01000111 11110001 00100000 00000000
再轉化為16進位為:47 F1 20 00,最後把它翻過來,就成了:00 20 F1 47。

==========================================================

按照IEEE浮點數標記法,將float型浮點數123.456f轉換為十六進位代碼。

整數部直接化二進位:100100011。

小數部的處理比較麻煩一些。

來看一下步驟:1 / 2 ^1位(為了方便,下面僅用2的指數來表示位),

第1位:0.456小於位階值0.5故為0;

2位,0.456大於位階值0.25,該位為1,並將0.45減去0.25得0.206進下一位;

3位,0.206大於位階值0.125,該位為1,並將0.206減去0.125得0.081進下一位;

4位,0.081大於0.0625,為1,並將0.081減去0.0625得0.0185進下一位;

5位0.0185小於0.03125,為0……

===========================

  //得到浮點尾數二進位

  

double d = 0.0d;  double d1 =0.456;  StringBuilder sb = new StringBuilder();  for (int i = 1; i < 19; i++) {      d = Math.pow(2,- i);      if(d1<d){        sb.append(0);      }else {        sb.append(1);       d1 = d1 - d;      }  }  System.out.println(sb.toString());

==================================

問題出來了,即使超過尾數的最大長度23位也除不盡!這就是著名的浮點數精度問題了。不過我在這裡不是要給大家講《數值計算》,用各種方法來提高計算精度,因為那太龐雜了,恐怕我講上一年也理不清個頭緒啊。我在這裡就僅把浮點數標記法講清楚便達到目的了。

反正最後一直求也求不盡,加上前面的整數部算夠24位就行了:1111011.01110100101111001。某BC問:“不是23位嗎?”我:“倒,不是說過了要把第一個1去掉嗎?當然要加一位嘍!”

現在開始向左移小數點,大家和我一起移,眾:“1、2、3……”好了,一共移了6位,6加上127得133(怎麼跟教小學生似的?呵呵~),二進位表示為:10000101,符號位為……再……

不說了,越說越囉嗦,大家自己看吧:
0  10000101  11101101110100101111001
42  F6  E9  79

32位浮點數(123.456)在記憶體中如果儲存為 79 E9  F6  42。
則先將其到序 42  F6  E9  79使其高位在前;
再將其轉化為二進位:0 10000101 11101101110100101111001
最高位是符號位 0表示是正值;
接下來8位是指數位
轉換為十進位再減127 結果6;
尾數部分右移6位111011.01110100101111001;
最前面添1 變為1111011.01110100101111001;
整數部分為1111011 轉為十進位123;
小數部分01110100101111001;
其中0對應2的-1次方,接下來的1對應2的-2次方:

即0*2(-1)+1*2(-2)+1*2(-3)+1*2(-4)+0*2(-5)+1*2(-6)......≈ 0.456

最後相加接近於0。456
結果123.456

==========================================================

Java 程式:

System.out.println("將 123.456F 浮點數轉換成16進位:");System.out.println("十進位位:"+Float.floatToIntBits(123.456f));System.out.println("十進位位轉二進位:"+Integer.toBinaryString(Float.floatToIntBits(123.456f)));String string = Integer.toHexString(Float.floatToIntBits(123.456f)).toUpperCase();System.out.println("十六進位:"+string);System.out.println("十六進位轉換成10進位位:"+Integer.parseInt(string, 16));System.out.println("十進位浮點數:"+Float.intBitsToFloat(Integer.parseInt(string, 16)));

===============================================================

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.