使用BigDecimal進行精確運算

一 . 簡介:

Java在java.math包中提供的API類BigDecimal,用來對超過16位有效位的數進行精確的運算。雙精度浮點型變量double能夠處理16位有效數。在實際應用中,須要對更大或者更小的數進行運算和處理。float和double只能用來作科學計算或者是工程計算,在商業計算中要用java.math.BigDecimal。BigDecimal所建立的是對象,咱們不能使用傳統的+、-、*、/等算術運算符直接對其對象進行數學運算,而必須調用其相對應的方法。方法中的參數也必須是BigDecimal的對象。構造器是類的特殊方法,專門用來建立對象,特別是帶有參數的對象。html

示例:

public class Test_1 {
     public static void main(String[] args) {
         System.out.println(0.06+0.01);
         System.out.println(1.0-0.42);
         System.out.println(4.015*100);
         System.out.println(303.1/1000);
     }
     
 }

運行結果:java

0.06999999999999999

0.5800000000000001

401.49999999999994

0.30310000000000004

你認爲你看錯了,但結果倒是是這樣的。問題在哪裏呢?緣由在於咱們的計算機是二進制的。浮點數沒有辦法是用二進制進行精確表示。咱們的CPU表示浮點數由兩個部分組成:指數和尾數,這樣的表示方法通常都會失去必定的精確度,有些浮點數運算也會產生必定的偏差。如:2.4的二進制表示並不是就是精確的2.4。反而最爲接近的二進制表示是 2.3999999999999999。浮點數的值其實是由一個特定的數學公式計算獲得的git

構造方法摘要
BigDecimal(BigInteger val) 
          將 BigInteger 轉換爲 BigDecimal。
BigDecimal(BigInteger unscaledVal, int scale) 
          將 BigInteger 非標度值和 int 標度轉換爲 BigDecimal。
BigDecimal(BigInteger unscaledVal, int scale, MathContext mc) 
          將 BigInteger 非標度值和 int 標度轉換爲 BigDecimal(根據上下文設置進行舍入)。
BigDecimal(BigInteger val, MathContext mc) 
          將 BigInteger 轉換爲 BigDecimal(根據上下文設置進行舍入)。
BigDecimal(char[] in) 
          將 BigDecimal 的字符數組表示形式轉換爲 BigDecimal,接受與 BigDecimal(String) 構造方法相同的字符序列。
BigDecimal(char[] in, int offset, int len) 
          將 BigDecimal 的字符數組表示形式轉換爲 BigDecimal,接受與 BigDecimal(String) 構造方法相同的字符序列,同時容許指定子數組。
BigDecimal(char[] in, int offset, int len, MathContext mc) 
          將 BigDecimal 的字符數組表示形式轉換爲 BigDecimal,接受與 BigDecimal(String) 構造方法相同的字符序列,同時容許指定子數組,並根據上下文設置進行舍入。
BigDecimal(char[] in, MathContext mc) 
          將 BigDecimal 的字符數組表示形式轉換爲 BigDecimal,接受與 BigDecimal(String) 構造方法相同的字符序列(根據上下文設置進行舍入)。
BigDecimal(double val) 
          將 double 轉換爲 BigDecimal,後者是 double 的二進制浮點值準確的十進制表示形式。
BigDecimal(double val, MathContext mc) 
          將 double 轉換爲 BigDecimal(根據上下文設置進行舍入)。
BigDecimal(int val) 
          將 int 轉換爲 BigDecimal。
BigDecimal(int val, MathContext mc) 
          將 int 轉換爲 BigDecimal(根據上下文設置進行舍入)。
BigDecimal(long val) 
          將 long 轉換爲 BigDecimal。
BigDecimal(long val, MathContext mc) 
          將 long 轉換爲 BigDecimal(根據上下文設置進行舍入)。
BigDecimal(String val) 
          將 BigDecimal 的字符串表示形式轉換爲 BigDecimal。
BigDecimal(String val, MathContext mc) 
          將 BigDecimal 的字符串表示形式轉換爲 BigDecimal,接受與 BigDecimal(String) 構造方法相同的字符串(按照上下文設置進行舍入)。

 

二. 使用:

1.在使用BigDecimal類來進行計算的時候,主要分爲如下步驟:api

  • 用float或者double變量構建BigDecimal對象:

( 1 ). BigDecimal BigDecimal(double d); //不容許使用,此構造方法的結果有必定的不可預知性。有人可能認爲在 Java 中寫入 new BigDecimal(0.1) 所建立的 BigDecimal 正好等於 0.1(非標度值 1,其標度爲 1),可是它實際上等於 0.1000000000000000055511151231257827021181583404541015625。這是由於 0.1 沒法準確地表示爲 double(或者說對於該狀況,不能表示爲任何有限長度的二進制小數)。這樣,傳入 到構造方法的值不會正好等於 0.1(雖然表面上等於該值)。
( 2 ). BigDecimal BigDecimal(String s); //經常使用,推薦使用
( 3 ). static BigDecimal valueOf(double d); //經常使用,推薦使用數組

  • 經過調用BigDecimal的加,減,乘,除等相應的方法進行算術運算:
BigDecimal add(BigDecimal)        //與另外一個BigDecimal對象相加,而後返回結果對象 
BigDecimal subtract(BigDecimal)   //與另外一個BigDecimal對象相減,而後返回這個對象 
BigDecimal multiply(BigDecimal)   //與另外一個BigDecimal對象相乘,而後返回這個對象 
BigDecimal divide(BigDecimal)     //與另外一個BigDecimal對象相除,而後返回這個對象
  • 把BigDecimal對象轉換成float,double,int等類型:
String toString()                 //將BigDecimal對象的數值轉換成字符串 
double doubleValue()              //將BigDecimal對象中的值以雙精度數返回 
float floatValue()                //將BigDecimal對象中的值以單精度數返回 
long longValue()                  //將BigDecimal對象中的值以長整數返回 
int intValue()                    //將BigDecimal對象中的值以整數返回

 

2.其餘經常使用方法:ide

/** 
 * 求餘數 
 * 返回值爲 (this % divisor) 的 BigDecimal 
 */  
BigDecimal remainder(BigDecimal divisor);  
  
/** 
 * 求相反數 
 * 返回值是 (-this) 的 BigDecimal 
 */  
BigDecimal negate();  
  
/** 
 * 將此 BigDecimal 與指定的 BigDecimal 比較 
 * 根據此方法,值相等但具備不一樣標度的兩個 BigDecimal 對象(如,2.0 和 2.00)被認爲是相等的; 
 * 相對六個 boolean 比較運算符 (<, ==, >, >=, !=, <=) 中每個運算符的各個方法,優先提供此方法; 
 * 建議使用如下語句執行上述比較:(x.compareTo(y) <op> 0), 其中 <op> 是六個比較運算符之一; 
 * 
 * 指定者:接口 Comparable<BigDecimal> 中的 compareTo 
 * 返回:當此 BigDecimal 在數字上小於、等於或大於 val 時,返回 -一、0 或 1 
 */  
int compareTo(BigDecimal val);

 

三. 與NumberFormat配合進行數據格式化

因爲java.text.NumberFormat類的format()方法可使用BigDecimal對象做爲其參數,能夠利用BigDecimal對超出16位有效數字的貨幣值,百分值,以及通常數值進行格式化控制。若是對NumberFormat不熟悉請點擊這裏this

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)); 
}

運行結果:spa

貸款金額:    ¥15,000.48
利率:    0.8%
利息:    ¥120.00
相關文章
相關標籤/搜索