2015-02-21

[轉載] [Java] BigDecimal的四則運算

轉載自:[Java] BigDecimal的四則運算

最近因為需要計算報表中的房物出租率,會用到BigDecimal的運算,目前只知道int, double, float等基本型態的我,連BigDecimal是三小都不太清楚,後來查了許多資料才知道原來BigDecimal可以用在精確的數學計算上面,許多商業用報表都需要用到BigDecimal型別。

BigDecimal有兩個較常用到的方法:
  1. BigDecimal(double val)
    Translates a double into a BigDecimal.
  2. BigDecimal(String val)
    Translates the String repre sentation of a BigDecimal into a BigDecimal.

API將上述方法解釋的非常清楚,而我們如果要精確計算,一定得把數值轉型成String型別,否則得到的結果會是有問題的。簡單來說,若要使用BigDecimal做加法計算必須有以下步驟:
  1. 需要先將兩個浮點數(double)轉為String,並分別宣告為BigDecimal
  2. 在其中一個浮點數使用add方法,傳入另一個浮點數作為參數
  3. 作為運算結果的參數(答案)也須宣告為BigDecimal
  4. 最後把運算的結果(BigDecimal)再轉換為浮點數

在BigDecimal的運算中,加為add, 減為sub,乘為multiply,除法為divide。在做運算之前需針對每一個變數new BigDecimal物件,舉例如下:
// 精確的加法運算,v1 為加數,v2 為被加數,return v1 + v2
public static double add(double v1,double v2){
    BigDecimal b1 = new BigDecimal(Double.toString(v1));
    BigDecimal b2 = new BigDecimal(Double.toString(v2));
    return b1.add(b2).doubleValue();
}

在運算之後若需四捨五入該怎麼辦呢?舉例如下:
// v 為需要四捨五入的數字,scale 為小數點後面要保留幾位數,return 四捨五入後的結果
public static double round(double v,int scale){
    if(scale < 0){
        throw new IllegalArgumentException(
            "The scale must be a positive integer or zero"
        );
    }
    BigDecimal b = new BigDecimal(Double.toString(v));
    BigDecimal one = new BigDecimal("1");
    return b.divide(one,scale,BigDecimal.ROUND_HALF_UP).doubleValue();
}

完整範例請參考以下文字:
import java.math.BigDecimal;
public class Testtest {

    public static void main(String[]args){
 
        // 宣告第一個需要運算的數值
        BigDecimal bigNumber = new BigDecimal("89.1234567890123456789"); 
  
        // 宣告第二個需要運算的數值
        BigDecimal bigRate = new BigDecimal(1000); 
  
        // 宣告運算後的答案為 bigResult
        BigDecimal bigResult = new BigDecimal(0);
  
        // bigResult 為 bigNumBer * bigRate
        bigResult = bigNumber.multiply(bigRate); 
  
        // 印出 bigResult
        System.out.println(bigResult.toString()); 
  
        // 將 bigNumber 四捨五入變為 double 型態
        double dData = bigNumber.doubleValue(); 
  
        // 印出 dDate
        System.out.println(dData);
  
        // 宣告 data2 為 bigNumber/bigRate 並四捨五入至小數點第二位
        double data2 = bigNumber
                           .divide(bigRate,2,BigDecimal.ROUND_HALF_UP)
                           .doubleValue();
  
        // 印出 data2
        System.out.println(data2);
    }
}

0 回應: