關於java BigDecimal 的使用,並將其運算方法封裝成工具類

最近在做數據統計的時候遇到了double 小數點精度丟失的問題,上網找了一些資料,發現 java 中的 BigDecimal 用於統計的計算更佳,下面把這個問題記錄下,時刻提醒自己。

首先,比較一下各個浮點型內容(轉自百度回答:https://zhidao.baidu.com/question/2119957025467035427.html):

float 單精度浮點 32bit,


double 雙精度浮點64bit,
decimal是高精度 128bit,浮點型。
float double 是 基本類型(primitive type),decimal不是。
float 有效數字7位,範圍 ±1.5 × 10E−45 to ±3.4 × 10E38
double 有效數字15/16 位,範圍 ±5.0 × 10 E−324 to ±1.7 × 10E308
decimal 有效數字 28/29 位,範圍 ±1.0 × 10E−28 to ±7.9 × 10E28
( E -- 下接幾次方)

decimal的有效位數很大,達到了28位,但是表示的數據範圍卻比float和double類型小。
使用的時候會對計算時的性能有影響。
常數寫法:
float f = 12.3F; (帶F)
double x=12.3; (不帶就是double)
decimal d = 12.30M; (帶M)

浮點數運算會有精度損失問題,有精度損失時程序不會報告,要程序員自己注意。


瞭解了上面三種浮點類型,我們就對 decimal 進一步瞭解了,下面就大致介紹一下java 中的BigDecimal 的使用。

BigDecimal(java.math.BigDecimal)一共有4個夠造方法,我在這就主要將他其中的兩種:

第一種:BigDecimal(double val)
Translates a double into a BigDecimal.

第二種:BigDecimal(String val)
Translates the String repre sentation of a BigDecimal into a BigDecimal.

我們更建議使用String來構造BigDecimal,這樣可以最大程度的避免精度丟失,但前提是String必須是一個數值。


下面提供 BigDecimal 的運算方法,大家可以把這些方法封裝成一個工具類,下面貼上代碼(代碼引用自:https://blog.csdn.net/huiwenjie168/article/details/6998140):

import java.math.BigDecimal;   
/**  
* 由於Java的簡單類型不能夠精確的對浮點數進行運算,這個工具類提供精  
* 確的浮點數運算,包括加減乘除和四捨五入。  
*/  
public class Arith{ //默認除法運算精度   
private static final int DEF_DIV_SCALE = 10; //這個類不能實例化   
private Arith(){   
}   
/**  
* 提供精確的加法運算。  
* @param v1 被加數  
* @param v2 加數  
* @return 兩個參數的和  
*/  
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();   
}   
/**  
* 提供精確的減法運算。  
* @param v1 被減數  
* @param v2 減數  
* @return 兩個參數的差  
*/  
public static double sub(double v1,double v2){   
BigDecimal b1 = new BigDecimal(Double.toString(v1));   
BigDecimal b2 = new BigDecimal(Double.toString(v2));   
return b1.subtract(b2).doubleValue();   
}   
/**  
* 提供精確的乘法運算。  
* @param v1 被乘數  
* @param v2 乘數  
* @return 兩個參數的積  
*/  
public static double mul(double v1,double v2){   
BigDecimal b1 = new BigDecimal(Double.toString(v1));   
BigDecimal b2 = new BigDecimal(Double.toString(v2));   
return b1.multiply(b2).doubleValue();   
}   
/**  
* 提供(相對)精確的除法運算,當發生除不盡的情況時,精確到  
* 小數點以後10位,以後的數字四捨五入。  
* @param v1 被除數  
* @param v2 除數  
* @return 兩個參數的商  
*/  
public static double div(double v1,double v2){   
return div(v1,v2,DEF_DIV_SCALE);   
}   
/**  
* 提供(相對)精確的除法運算。當發生除不盡的情況時,由scale參數指  
* 定精度,以後的數字四捨五入。  
* @param v1 被除數  
* @param v2 除數  
* @param scale 表示表示需要精確到小數點以後幾位。  
* @return 兩個參數的商  
*/  
public static double div(double v1,double v2,int scale){   
if(scale<0){   
throw new IllegalArgumentException(   
"The scale must be a positive integer or zero");   
}   
BigDecimal b1 = new BigDecimal(Double.toString(v1));   
BigDecimal b2 = new BigDecimal(Double.toString(v2));   
return b1.divide(b2,scale,BigDecimal.ROUND_HALF_UP).doubleValue();   
}   
/**  
* 提供精確的小數位四捨五入處理。  
* @param v 需要四捨五入的數字  
* @param 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();   
}   
};
至此,關於java BigDecimal 的使用就先講到這兒,希望此文章能幫助到各位技術開發人員!
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章