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