爲什麼浮點數比int,long表示的範圍要大?

背景:float 底層用4個字節32位來表示,爲什麼範圍比int,long還要大?

   整數在計算機底層採用補碼的形式表示,除去首位的符號位,剩餘的位數即表示數值的範圍,也就是位數越多,範圍越大,那麼對於單精度浮點數float,和雙精度浮點數double,它們底層的數據結構是什麼,它們的範圍又是如何計算的,它們的精度範圍又是多少那,接下來將從6方面進行闡述。

1  IEEE754浮點數標準

IEEE754標準包含一組實數的二進制表示法。它有三部分組成:

  • 符號位
  • 指數位
  • 尾數位

三種精度的浮點數各個部分位數如下:

用float來舉例:

 

第一部分用來存儲符號位(sign)用來區分正負數0正1負。

第二部分用來存儲指數(exponent)指數也有正負之分,指數位確定大小範圍。

第三部分用來存儲小數(fraction),小數位決定了計算精度,因爲小數位能表示的數越大,精度越大,數值越準確。

備註:浮點數在內存中是按科學計數法來存儲的,其整數部分始終是一個隱含着的“1”

2 第二部分(指數位確定範圍)

    需要注意的是指數可能是負數,也有可能是正數,即指數是有符號整數,而有符號整數的計算是比無符號整數麻煩的。所以爲了減少不必要的麻煩,在實際存儲指數的時候,需要把指數轉換成無符號整數

那麼怎麼轉換呢?注意到float的指數部分是8位,則指數的取值範圍是 -126到+127,爲了消除負數帶來的實際計算上的影響(比如比較大小,加減法等),可以在實際存儲的時候,給指數做一個簡單的映射,加上一個偏移量,比如float的指數偏移量爲127,對應的double類型,存儲的時候指數偏移量是1023,這樣就不會有負數出現了

3 第三部分(小數位確定精度)

  float和double的精度是由尾數的位數來決定的。浮點數在內存中是按科學計數法來存儲的,其整數部分始終是一個隱含着的“1”,由於它是不變的,故不能對精度造成影響。
float:2^23 = 8388608,一共七位,由於最左爲1的一位省略了,這意味着最多能表示8位數,但絕對能保證的爲7位,也即float的精度爲7~8位有效數字(算上整數的一位),不算整數位的話能只有7位,所以能準確表示的10進制也就6位。
double:2^52 = 4503599627370496,一共16位,同理,double的精度爲16~17位,能準確表示的10進制也就15位。

4 注意點

  • 程序中應儘量避免浮點數的比較,例如System.out.println(2.00-1.10==0.90),永遠返回false.
  • float、double類型的運算往往都不準確

5 正確的方式

  •   利用整數來表示小數int或者long,例如1.01元,則可以以分爲單位來表示。
  • 利用BigDecimal進行浮點型運算,但是注意一定要使用String類型的構造方法,如果使用浮點型構造方法也不能得到準確的結果。

6 福利彩蛋(浮點數保留2位的幾種方法)

     1> double dd = (double) (Math.round(1/(float)num*100)/100.0); //先乘以100後除以100,對浮點數做進位處理。

     2> DecimalFormat       df=new DecimalFormat("###.00")

      3>String ss = String.format("%1.2f", 1.1256); 

      4> NumberFormat ddf1=NumberFormat.getNumberInstance() ; ddf1.setMaximumFractionDigits(2);

      5> BigDecimal b = new BigDecimal(T); T = b.setScale(2,BigDecimal.ROUND_HALF_UP).floatValue();

  
​​​​​​​

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