BigDecimal用法詳解


BigDecimal用法詳解

* Java在java.math包中提供的API類BigDecimal,用來對超過16位有效位的數進行精確的運算。

* 雙精度浮點型變量double可以處理16位有效數。在實際應用中,需要對更大或者更小的數進行運算和處理。

* float和double只能用來做科學計算或者是工程計算,在商業計算中要用java.math.BigDecimal。

* BigDecimal所創建的是對象,我們不能使用傳統的+、-、*、/等算術運算符直接對其對象進行數學運算,而必須調用其相對應的方法。方法中的參數也必須是BigDecimal的對象。

* 構造器是類的特殊方法,專門用來創建對象,特別是帶有參數的對象。

1.構造器描述

BigDecimal(int)   創建一個具有參數所指定整數值的對象。 

BigDecimal(double) 創建一個具有參數所指定雙精度值的對象。(不建議采用) 

BigDecimal(long)   創建一個具有參數所指定長整數值的對象。 

BigDecimal(String) 創建一個具有參數所指定以字符串表示的數值的對象。

* 為什么不建議采用第二種構造方法?

a.有人可能認為在Java中寫入newBigDecimal(0.1)所創建的BigDecimal正好等於 0.1(非標度值 1,其標度為 1),但是它實際上等於0.1000000000000000055511151231257827021181583404541015625。

b.計算機是二進制的。浮點數沒有辦法是用二進制進行精確表示。我們的CPU表示浮點數由兩個部分組成:指數和尾數,這樣的表示方法一般都會失去一定的精確度,有些浮點數運算也會產生一定的誤差。

c.可以先將Double型轉換成String型,使用String構造方法。

2.方法描述

add(BigDecimal)     BigDecimal對象中的值相加,然后返回這個對象。 

subtract(BigDecimal) BigDecimal對象中的值相減,然后返回這個對象。 

multiply(BigDecimal)   BigDecimal對象中的值相乘,然后返回這個對象。 

divide(BigDecimal)    BigDecimal對象中的值相除,然后返回這個對象。

abs()   BigDecimal對象中的值取絕對值,然后返回這個對象。

toString()         將BigDecimal對象的數值轉換成字符串。 

doubleValue()       將BigDecimal對象中的值以雙精度數返回。 

floatValue()        將BigDecimal對象中的值以單精度數返回。 

longValue()         將BigDecimal對象中的值以長整數返回。 

intValue()         將BigDecimal對象中的值以整數返回。

這里有一點需要注意的是除法運算divide.

BigDecimal除法可能出現不能整除的情況,比如 4.5/1.3,

這時會報錯java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.

其實divide方法有可以傳三個參數

public BigDecimal divide(BigDecimal divisor, int scale, int roundingMode) 

第一參數表示除數, 第二個參數表示小數點后保留位數,

第三個參數表示舍入模式,只有在作除法運算或四舍五入時才用到舍入模式,有下面這幾種

 

 ROUND_UP           //向遠離0的方向舍入;在丟棄非零部分之前始終增加數字(始終對非零舍棄部分前面的數字加1)。
 ROUND_DOWN         //向零方向舍入;在丟棄某部分之前始終不增加數字(從不對舍棄部分前面的數字加1,即截短)。
 ROUND_CEILING      //向正無窮方向舍入;如果 BigDecimal 為正,則舍入行為與 ROUND_UP 相同; 如果為負,則舍入行為與 ROUND_DOWN 相同。
 ROUND_FLOOR        //向負無窮方向舍入;如果 BigDecimal 為正,則舍入行為與 ROUND_DOWN 相同;如果為負,則舍入行為與 ROUND_UP 相同。
 ROUND_HALF_UP      //向(距離)最近的一邊舍入,除非兩邊(的距離)是相等,如果是這樣,向上舍入, 1.55保留一位小數結果為1.6
 ROUND_HALF_DOWN    //向(距離)最近的一邊舍入,除非兩邊(的距離)是相等,如果是這樣,向下舍入, 例如1.55 保留一位小數結果為1.5
 ROUND_HALF_EVEN    //向(距離)最近的一邊舍入,除非兩邊(的距離)是相等,如果是這樣,如果保留位數是奇數,使用ROUND_HALF_UP,如果是偶數,使用ROUND_HALF_DOWN
 ROUND_UNNECESSARY  //計算結果是精確的,不需要舍入模式

按照各自的需要,可傳入合適的第三個參數。四舍五入采用 ROUND_HALF_UP

需要對BigDecimal進行截斷和四舍五入可用setScale方法,例:

public static void main(String[] args) { BigDecimal a = new BigDecimal("4.5635"); a = a.setScale(3, RoundingMode.HALF_UP);    //保留3位小數,且四舍五入 System.out.println(a);
    }

 加減乘除其實最終都返回的是一個新的BigDecimal對象,因為BigInteger與BigDecimal都是不可變的(immutable)的,在進行每一步運算時,都會產生一個新的對象 

 public static void main(String[] args) { BigDecimal a = new BigDecimal("4.5"); BigDecimal b = new BigDecimal("1.5"); a.add(b); System.out.println(a); //輸出4.5. 加減乘除方法會返回一個新的BigDecimal對象,原來的a不變
 }

3.格式化及例子

由於NumberFormat類的format()方法可以使用BigDecimal對象作為其參數,可以利用BigDecimal對超出16位有效數字的貨幣值,百分值,以及一般數值進行格式化控制。

以利用BigDecimal對貨幣和百分比格式化為例。首先,創建BigDecimal對象,進行BigDecimal的算術運算后,分別建立對貨幣和百分比格式化的引用,最后利用BigDecimal對象作為format()方法的參數,輸出其格式化的貨幣值和百分比。

public static void main(String[] args) { NumberFormat currency = NumberFormat.getCurrencyInstance(); //建立貨幣格式化引用 
    NumberFormat percent = NumberFormat.getPercentInstance();  //建立百分比格式化引用 
    percent.setMaximumFractionDigits(3); //百分比小數點最多3位 
    BigDecimal loanAmount = new BigDecimal("15000.48"); //貸款金額
    BigDecimal interestRate = new BigDecimal("0.008"); //利率 
    BigDecimal interest = loanAmount.multiply(interestRate); //相乘
    System.out.println("貸款金額:\t" + currency.format(loanAmount)); System.out.println("利率:\t" + percent.format(interestRate)); System.out.println("利息:\t" + currency.format(interest)); } 運行結果如下: 貸款金額: ¥15,000.48 利率: 0.8% 利息: ¥120.00

4. BigDecimal比較

BigDecimal是通過使用compareTo(BigDecimal)來比較的,具體比較情況如下:

public static void main(String[] args) { BigDecimal a = new BigDecimal("1"); BigDecimal b = new BigDecimal("2"); BigDecimal c = new BigDecimal("1"); int result1 = a.compareTo(b); int result2 = a.compareTo(c); int result3 = b.compareTo(a); System.out.println(result1); System.out.println(result2); System.out.println(result3); }

 

打印結果是:-1、0、1,即左邊比右邊數大,返回1,相等返回0,比右邊小返回-1。

注意不能使用equals方法來比較大小。

使用BigDecimal的壞處是性能比double和float差,在處理龐大,復雜的運算時尤為明顯,因根據實際需求決定使用哪種類型。

5.總結

(1)商業計算使用BigDecimal。

(2)盡量使用參數類型為String的構造函數。

(3) BigDecimal都是不可變的(immutable)的,在進行每一步運算時,都會產生一個新的對象,所以在做加減乘除運算時千萬要保存操作后的值。 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM