Java中浮點數的表示與定義

目錄

存儲形式

測試代碼

轉換過程:

例:以上述測試的值 20.3 爲例

再來一例: 0.6f

參考資料:


存儲形式

存儲形式?不用多說,肯定是二進制啦!

IEEE 754 規定,對於 32 位的浮點數,最高位(第 31 位)是符號位 s,接着的 8 位(30 ~ 23)是指數 E,剩下的 23 位(22 ~ 0)爲有效數字 M,對於 64 位的浮點數,最高位(第 63 位)是符號位 s,接着的 11 位(第 62 ~ 52 位)是指數 E,剩下的 52位(第 51 ~ 0)爲有效數字 M。

SEEEEEEE EMMMMMMM MMMMMMMM MMMMMMMM

接下來就來砍一下:,一個 Float 在計算機中存儲是個啥亞子:

測試代碼

public static void testFloatStrore(String[] args) {
    Float f = 20.3f;
    System.out.println(Integer.toBinaryString(Float.floatToIntBits(f)));
}

運行結果:

可以看到 20.3f 存儲的值是有 31 位,因爲它是個正數,最高位爲0,省略。

轉換過程:

例:以上述測試的值 20.3 爲例

  • 將值從十進制轉二進制:

    整數部分:20 => 10100 (5 個 bit 位)

    小數部分

        方式:

            1)小數部分 乘 2,積的整數部分如果爲1;則計1,否則計0。 

            2)再對剩下的小數部分 乘 2,再計出 1 或 0 。 

            3)重複以上步驟,直至達到需要的精度。

        0.3 => 01001100 11001100 1100...(無限循環)

    合起來(最高位 0):10100.01001100 11001100 11001100 11...

  •     小數點進行左移至小數點前只剩一位,值保持不變:1.0100010 01100110 01100110 0110011... * 2 ^ 4,左移了四位
  •     浮點數有效位(底數): 因爲小數點前必爲1,IEEE 規定只記錄小數點後的位就好。

                 所以,此處的底數爲(從高位取 23 個位):01000100 11001100 1100110,

  •     指數位:偏移量加上一個固定的偏移值 127,即:01111111

        127 + 4 = 131 => 10000011

  •     最終結果(符號位 、 指數位 、 浮點數有效位):0 10000011 01000100 11001100 1100110

            !!!以補碼形式進行存儲

再來一例: 0.6f

運行上面的測試代碼後的輸出結果:

0.6 十進制轉二進制:0.10011001 10011001 1001...

上一步結果規格化: 右移 1 位,1.0011001 10011001 * 2 ^ -1,-1 + 127,即:126 => 01111110

0 01111110 00110011 00110011 0011001

指數位不全爲0,所以尾數附加位爲1,否則尾數附加位爲0

2^(126-127) * (2 ^ 0 + 2^-3 + 2^-4 + + 2^-7 + 2^-8 + 2^-11 + 2^-12 + 2^-15 + 2^-16)

但是,上面的測試代碼的運行結果和我們推算出的結果並不一致,推算出來的結果要比運行結果小 1 個 bit 位!

但是此處爲啥會出現這樣的結果?

Float 的尾數部分最多隻能表示 23 位。但是這個小數是個無限循環的,比如說 0.1f 爲了能表示 0.1f,只能模仿十進制進行四捨五入了,但二進制只有 0 和 1 , 於是變爲 0 舍 1 入。

參考資料:

http://www.ruanyifeng.com/blog/2010/06/ieee_floating-point_representation.html

https://github.com/sanshuiwang/Blog/issues/9

https://www.zengdongwu.com/article1.html

https://www.jianshu.com/p/d52a542bb363 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章