閱讀644 返回首頁    go 阿裏雲 go 技術社區[雲棲]


Java中float,double為什麼會丟失精度。

Effective Java Item 48: Avoid float and double if exact answers are required

 對於精確計算不提倡使用float,double,因為會丟失精度,這是為什麼呢? 讓我細細說來

1. 什麼是浮點數?

表示一個數字如100.2,可以是Fixed point也就是100.2,也可以是Floating point(也就是科學計數法scientific notation)1.002 ×  102.
通常是以第一個非零數字作為小數點前的數,也被稱為normalized form,也就是說上麵的數字不會表示成100.2  × 100
或0.1002  × 103
浮點數的優點是能表示Fixed point無法表示的超大和超小數值

2. IEEE Standard 754 關於floating number在計算機中表示的定義。
Java中float(單精度浮點),double(雙精度浮點)也遵照次標準設計。

  • The sign bit is 0 for positive, 1 for negative. 符號位0是正,1是負
  • The exponent(冪值)'s base is two. 冪值是2
  • The exponent field contains 127 plus the true exponent for single-precision(單精度),
    or 1023 plus the true exponent for double precision(雙精度).

  • The first bit of the mantissa is typically assumed to be 1.f, where f is the field of fraction bits.
    尾數中第一位任何情況下都是1(因為binary中隻有0,1),所以不用占空間,所以fraction bits都用來存儲.f
圖示如下:
float(32位):

double(64位):


3.為什麼會有精度丟失?
拿單精度浮點float為例,正常的整數integer,可以用全部32位表示數字,而Single Precision隻能有24位存儲數值,這24位是沒辦法
match 32位的精度的,所以就會丟失。例如:
      11110000 11001100 10101010 00001111  // 32-bit integer
  = +1.1110000 11001100 10101010 x 231     // Single-Precision Float
  =   11110000 11001100 10101010 00000000  // Corresponding Value

4.如何解決?
通常會用long和BigDecimal來替代float,double。比如eBay內部的Money類,
就是用long來做internal value存儲amount的數值的。

5.Java考題常出現
當你不聲明的時候,默認小數都用double來表示,所以如果要用float的話,則應該在其後加上f 
例如:float a=1.3; 
則會提示不能將double轉化成float  這是窄型轉化。
如果要用float來修飾的話,則應該使用float a=1.3f 

6.Java變量取值範圍
byte的取值範圍為-128~127,占用1個字節(-2的7次方到2的7次方-1)
short的取值範圍為-32768~32767,占用2個字節(-2的15次方到2的15次方-1)
int的取值範圍為(-2147483648~2147483647),占用4個字節(-2的31次方到2的31次方-1)
long的取值範圍為(-9223372036854774808~9223372036854774807),占用8個字節(-2的63次方到2的63次方-1)
float (單精度浮點)約等於(-1 x 2-127 ~ +1 x 2127),占4個字節(指數段8bits)
double(雙精度浮點)約等於(-1 x 2-1023 ~ +1 x 21023),占8個字節(指數段11bits)

最後更新:2017-04-02 06:52:08

  上一篇:go Email Configuration -redmine
  下一篇:go Android手機分辨率基礎知識(DPI,DIP計算)