LetsCoding.cn

          天地之間有桿秤,拿秤砣砸老百姓。

          初窺JVM浮點運算

          歡迎來到“Under The Hood”第四期。上期我們討論了JVM的字節碼指令集,本期我們繼續這個話題。本文我們來看看JVM中的浮點運算

          JVM支持IEEE-754浮點數標準(1985)。該標準定義了32位和64位浮點數的格式,以及在此之上的各種運算。在JVM中,浮點運算是基于32位float數和64位double數的。對每個操作float數的字節碼,都有一個對應的操作double數的版本。

          浮點數由4部分組成:數符(sign),尾數(mantissa),基數(radix)和階碼(exponent)。數符取1或-1。尾數是一個正數,它持有浮點數的有效位。階碼是尾數和符號位應該乘以的基數的正(負)冪數。這4個部分用下面的公式得到浮點數的值:

          sign * mantissa * radixexponent

          浮點數有很多種表現形式,因為你總是可以把浮點數的尾數乘以基數的某次冪,然后通過改變階碼的方式獲得原先的值。例如,-5可以寫成如下以10為基數的形式:   

          Sign Mantissa Radix Exponent
          -1 50 10 -1
          -1 5 10 0
          -1 0.5 10 1
          -1 0.05 10 2

          每個浮點數都有一個規范化的表示形式。如果浮點數的尾數符合下面的公式,我們就說這個浮點數是規范化的。

          1/radix <= mantissa < 1

          規范化的以10為基數的浮點數,尾數的小數點出現在第一個非0的有效位前面。-5的規范化形式是-1*0.5*10 1。也就是說,規范化的浮點數中,小數點的左邊是0,右邊第一位不是0。其他不是這種形式的浮點數都是非規范化數。注意,0沒有規范化的形式,因為它沒有非0數放在小數點后面。數字0們總是感嘆“為什么要規范化我們呢?”。

          JVM中的浮點數以2為基數,所以JVM中的浮點數值用下面的公式獲得:

          sign * mantissa * 2exponent

          JVM中的浮點數的尾數用2進制數表示。規范化的二進制數小數點出現在非0最高有效位前面。由于二進制數系統只有2個數字,1和0,所以最高有效位上的數字總是1。

          float和double數的最高有效位是它的符號位,float的最后23位是尾數位,而double則為最后52位。階碼處在符號位和尾數中間,float為8位,double為11位。float的完整2進制形式如下,s表示符號位,e表示階碼,m表示尾數。

          s eeeeeeee mmmmmmmmmmmmmmmmmmmmmmm

          正數的符號位為0,負數的符號位為1。尾數總是一個正的二進制數,但不是二進制補碼數。如果符號位為1,浮點數的值是負的,但尾數仍然是正的。

          階碼有3種解釋方式。如果階碼位全是1,意味著這是一個特殊的浮點數,表示正無窮或負無窮,或者不是一個數(NaN)。NaN是特定運算的結果,比如除法的除數是0。階碼的所有位為0,表示這是一個非規范化的浮點數。除上面2種情況之外的階碼,都是規范化浮點數的一部分。

          尾數部分其實隱式包含了一個額外的精度位。float數的尾數占23位,卻有24個精度位;同一樣的,double數的尾數占52位,卻有53個精度位。因為尾數部分的最高有效位是可以被預測的,所以并沒有包含在尾數中。JVM中,浮點數的階碼可以指明該數是不是一個規范化浮點數。如果階碼位全0,則為非規范化數,且最高有效位肯定是0。其他情況下,則為規范化浮點數,且最高有效位肯定是1。

          在JVM中,任何浮點運算都不會拋出異常。類似除數為0的問題操作,JVM會返回一些特殊值,比如正/負無窮,或NaN。尾數位全是0的情況下,如果階碼位全是1,符號位是0,則表示正無窮;如果階碼位全是1,符號位是1,則表示負無窮。如果階碼位全是1,尾數位不全是0,則表示NaN。JVM總是為NaN使用相同的尾數:最高有效位是1,其他全為0。下表列出了上面提到的3中特殊值:

          Special float values Float bits (sign exponent mantissa)
          +Infinity 0 11111111 00000000000000000000000
          -Infinity  1 11111111 00000000000000000000000
          NaN 1 11111111 10000000000000000000000

          非全0和非全1的階碼表示規范化尾數要乘以的2的冪數。可以把階碼當做一個正數,然后減去一個偏移量,這樣就能得到實際的冪數。對float數來說,偏移量是126;而double數,則為1023。例如,一個float數的階碼為00000001,則冪數為-125(1 – 126),這是float中最小的冪數。再看一個例子,如果階碼是11111110,則冪數為128(254 – 126),這是float中最大的冪數。下表列出了一些正規化的浮點數:

          Normalized float values Float bits (sign exponent mantissa) Unbiased exponent
          Largest positive (finite) float 0 11111110 11111111111111111111111 128
          Largest negative (finite) float 1 11111110 11111111111111111111111 128
          Smallest normalized float  1 00000001 00000000000000000000000 -125
          Pi 0 10000000 10010010000111111011011 2

          階碼位全0,說明尾數沒有規范化,也隱含說明了最高有效為是0,而不是1。這種情況下,冪數為浮點數的最小冪數。對float來說,是-125。這意味著,規范化尾數乘以2 -125的浮點數,它的階碼為00000001,而非規范化尾數乘以2 -125的浮點數,它的階碼為00000000。階碼范圍底端的非規范化數修正值,使得下溢出較為平緩。如果最小階碼用來表示規范化數,下溢成0的最小數值會更大一些。 換句話說,讓最小階碼表示非規范化數,可以使浮點數能表示更小的數值。雖然非規范化數的精度沒有規范化數高,但是,這相對于階碼一旦達到最小規范化數值,浮點數就會下溢成0來說,非規范化數更好一些。

          Denormalized float values Float bits (sign exponent mantissa)
          Smallest positive (non-zero) float 0 00000000 00000000000000000000001
          Smallest negative (non-zero) float 1 00000000 00000000000000000000001
          Largest denormalized float  1 00000000 11111111111111111111111
          Positive zero 0 00000000 00000000000000000000000
          Negative zero 1 00000000 00000000000000000000000

          本文譯自:Floating-point arithmetic

          原創文章,轉載請注明: 轉載自碼農合作社
          本文鏈接地址: 初窺JVM浮點運算

          posted on 2014-05-26 15:09 Rolandz 閱讀(1049) 評論(1)  編輯  收藏 所屬分類: 編程實踐

          評論

          # re: 初窺JVM浮點運算 2014-05-26 15:24 腌漬府

          對于這方面的知識,我真的是有很多不懂,在博主這里學到了,以后多多來此學習。  回復  更多評論   

          導航

          統計

          留言簿(1)

          隨筆分類(12)

          隨筆檔案(19)

          積分與排名

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 晋城| 沙田区| 泸溪县| 梁河县| 枣庄市| 侯马市| 石柱| 肇东市| 武义县| 望城县| 游戏| 扬州市| 云梦县| 高陵县| 离岛区| 昌都县| 桂东县| 仁寿县| 綦江县| 黄梅县| 新乡县| 永修县| 武强县| 手机| 祁东县| 莱阳市| 平利县| 泗洪县| 长顺县| 泰来县| 砚山县| 江陵县| 武宣县| 方山县| 瑞金市| 中牟县| 南木林县| 密云县| 乐安县| 武平县| 当雄县|