close
文章出處

轉自:http://superivan.iteye.com/blog/963628

[1] 精確的浮點運算: 
在Java里面,有時候為了保證數值的準確性需要精確的數據,先提供一個例子就可以發現問題了: 

public class FloatNumberTester {
    public static void main(String args[]){
        System.out.println(0.05+0.01);
        System.out.println(1.0 - 0.42);
        System.out.println(4.015 * 100);
        System.out.println(123.3 / 100);
    }
}

 按照我們的期待,上邊應該是什么結果呢,但是看輸出我們就會發現問題了: 

0.060000000000000005
0.5800000000000001
401.49999999999994
1.2329999999999999

這樣的話這個問題就相對嚴重了,如果我們使用123.3元交易,計算機卻因為1.2329999999999999而拒絕了交易,豈不是和實際情況大相徑庭。 

[2] 四舍五入: 
另外的一個計算問題,就是四舍五入。但是Java的計算本身是不能夠支持四舍五入的,比如: 

public class GetThrowTester {
    public static void main(String args[]){
        System.out.println(4.015 * 100.0);
    }
}

這個輸出為: 

401.49999999999994 
所以就會發現這種情況并不能保證四舍五入,如果要四舍五入,只有一種方法java.text.DecimalFormat:  

import java.text.DecimalFormat;
public class NumberFormatMain {
    public static void main(String args[]){
        System.out.println(new DecimalFormat("0.00").format(4.025));
        System.out.println(new DecimalFormat("0.00").format(4.024));
    }
}

上邊代碼輸出為:  

4.02
4.02

發現問題了么?因為DecimalFormat使用的舍入模式, 舍入模式 詳情參見本文最后部分。 
[3] 浮點輸出: 
  Java浮點類型數值在大于9999999.0就自動轉化成為科學計數法,看看下邊的例子: 

 public class FloatCounter {
    public static void main(String args[]){
        System.out.println(9969999999.04);
        System.out.println(199999999.04);
        System.out.println(1000000011.01);
        System.out.println(9999999.04);
    }
}  
 輸出結果為:    
9.96999999904E9 
1.9999999904E8 
1.00000001101E9 
9999999.04

但是有時候我們不需要科學計數法,而是轉換成為字符串,所以這樣可能會有點麻煩。 
總結: 
所以在項目當中,對于浮點類型以及大整數的運算 還是盡量不要用double,long等基本數據類型以及其包裝類,還是用Java中提供的BigDecimal,BigInteger等大數值類型來代替吧。 
但這里特別說明一下BigDecimal類的兩個構造函數的區別,他們分別是: 
new BigDecimal(String  val ) 和 new BigDecimal(double  val ) 
先看例子:  

public class BigDecimalMain {
    public static void main(String args[]){
        System.out.println(new BigDecimal(123456789.01).toString());
        System.out.println(new BigDecimal("123456789.01").toString());
    }
}

輸出結果有一次令人意外了,同時兩者之間的區別也一目了然了: 

123456789.01000000536441802978515625 
123456789.01

所以在 就是想利用double原始類型進行了相關計算之后再轉成BigDecimal類型 的場合下,為了防止精度出現偏離,建議使用參數為String類型的該構造方法。即new BigDecimal(String  val )。 

補充:

  • BigDecimal都是不可變的(immutable)的,在進行每一步運算時,都會產生一個新的對象,由于創建對象會引起開銷,因此它們不適合于大量的數學運算,應盡量使用longfloatdouble等基本類型做科學計算或者工程計算。設計BigIntegerBigDecimal的目的是用來精確地表示大整數和小數,常用于商業計算中。
  • BigDecimal夠造方法的參數類型有4種,其中的兩個用BigInteger構造,另一個是用double構造,還有一個使用String構造。應該避免使用double構造BigDecimal,因為:有些數字用double根本無法精確表示,傳給BigDecimal構造方法時就已經不精確了。比如,new BigDecimal(0.1)得到的值是0.1000000000000000055511151231257827021181583404541015625。使用new BigDecimal("0.1")得到的值是0.1。因此,如果需要精確計算,用String構造BigDecimal,避免用double構造,盡管它看起來更簡單! 
  • equals()方法認為0.10.1是相等的,返回true,而認為0.100.1是不等的,結果返回false。方法compareTo()則認為0.10.1相等,0.100.1也相等。所以在從數值上比較兩個BigDecimal值時,應該使用compareTo()而不是 equals()
  • 另外還有一些情形,任意精度的小數運算仍不能表示精確結果。例如,1除以9會產生無限循環的小數 .111111...。出于這個原因,在進行除法運算時,BigDecimal可以讓您顯式地控制舍入。

不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 AutoPoster 的頭像
    AutoPoster

    互聯網 - 大數據

    AutoPoster 發表在 痞客邦 留言(0) 人氣()