天天看點

float與double基本資料類型分析

float 大小為 32-bit  

存儲的結構:1位符号位,8位指數(幂),23位尾數

double 大小為 64-bit    

存儲的結構:1位符号位,11位指數(幂),52位尾數

float與double結構類似,下面以float為例子做分析:

1、通過程式的方式擷取float的二進制表示:

public class FloatTest {  
    public static void main(String[] args) {  
        float f = 8;  
        //因為int型與float型在記憶體中的長度相同,用floatToIntBits()可以把float中的二進制标示轉為int型表示。類似double可轉為long
        int i = Float.floatToIntBits(f); 
        System.out.println(Integer.toBinaryString(i)); 
    } 
}       

2、通過計算的方式擷取float的二進制表示:

以float f = 20014999 為例

  1)20014999 的二進制為1001100010110011110010111

  2)規格化後 1.001100010110011110010111*2^24

     尾數為001100010110011110010111

       此時24位,但float的尾數隻有23位。四舍五入後為00110001011001111001100

  3)幂為24+127 二進制為:10010111。

    其中127為 float的偏移附加,double的偏移附加為1023。具體解釋參照:IEEE 754 (二進制浮點數算術标準)

  4)加上符号位0。  0表示正數,1表示負數

  最後,記憶體中的表示為:0 10010111 00110001011001111001100

上面的過程中可以看出float精度丢失的原因。需要高精度,如金額的計算不能用浮點型,一般可用BigDecimal。

使用BigDecimal需要注意的一點是:BigDecimal 也有一些令人奇怪的行為。尤其在使用 equals() 方法來檢測數值之間是否相等時要小心。 equals() 方法認為,兩個表示同一個數但換算值不同(例如, 100.00 和 100.000 )的 BigDecimal 值是不相等的。然而, compareTo() 方法會認為這兩個數是相等的,是以在從數值上比較兩個 BigDecimal 值時,應該使用 compareTo() 而不是 equals() 。

 3、float、double、long型 常量的表示問題。

  float 型常量後面加F  or   f   如   3.14f

  double 型常量後面加D  or   d   或者不加    3.14d  or  3.14(預設為雙精度)

  long 型常量   加L or  l 

  int 型常量     不加字尾

  一般我們都不加這個字尾,其實是因為程式做了類型轉換。

  但當超出範圍時需要注意。

  如:

long L1 = 8888888888;//會報錯,因為8888888888為int型常量,但超出了int的範圍。      

*花邊知識:

1、計算機上表達實數有兩中方法:定點表示(fixed-point)和浮點表示(floating-point)。

2、上面的提到的方法Float.floatToIntBits()的jdk 1.7的源碼如下:

public static int floatToIntBits(float value) {
        int result = floatToRawIntBits(value);
        // Check for NaN based on values of bit fields, maximum
        // exponent and nonzero significand.
        if ( ((result & FloatConsts.EXP_BIT_MASK) ==
              FloatConsts.EXP_BIT_MASK) &&
             (result & FloatConsts.SIGNIF_BIT_MASK) != 0)
            result = 0x7fc00000;
        return result;
    }      

其中的 floatToRawIntBits();方法的實作為:

public static native int floatToRawIntBits(float value);      

這裡用到native因為這個方法的實作需要操作記憶體,是以但在java無法實作,隻能通過調用C語言來實作底層的操作。

 3、前人研究:

 java float double精度為什麼會丢失?淺談java的浮點數精度問題

http://blog.csdn.net/abing37/archive/2010/02/27/5332798.aspx

Java中的double類型資料存儲探析

http://blog.csdn.net/softwater007/archive/2008/11/18/3330619.aspx

IEEE754 學習總結

http://www.pediy.com/bbshtml/BBS6/pediy6610.htm

使用浮點數和小數中的陷阱

http://www.360doc.com/content/07/0308/10/14474_388882.shtml

4.相關規範

IEEE754:http://babbage.cs.qc.edu/courses/cs341/IEEE-754references.html

SUN 公司的 http://docs.sun.com/source/806-3568/ncg_math.html

轉載于:https://www.cnblogs.com/wuchangming/archive/2013/03/26/2983559.html