第一版
java.math.RoundingMode 幾個參數詳解
第二版
roundMode是指舍位時候的模式,傳參數的時候用BigDecimal.ROUND_XXXX_XXX,
有以下例子是setScale(0,BigDecimal.ROUND_XXXX_XXX));的情況。如果保留小數位數不是零,如
setScale(2,BigDecimal.ROUND_XXXX_XXX)); 是 2 ,則 此數字的小數位數要大於2位。第三位才是要取舍得位。
ROUND_CEILING: 舍位時往正無窮方向移動 1.1->2 1.5->2 1.8->2 -1.1->-1 -1.5->-1 -1.8->-1
ROUND_DOWN:向0的方向移動1.1->1 1.5->1 1.8->1 -1.1->-1 -1.5->-1 -1.8>-1
ROUND_FLOOR:與CEILING相反,往負無窮 1.1->1 1.5->1 1.8->1 -1.1->-2 -1.5->-2 -1.8->-2
ROUND_HALF_DOWN:以5為分界線,或曰五舍六入1.5->1 1.6->1 -1.5->-1 -1.6->-2 1.15->1.1 1.16->1.2 1.55->1.6 1.56->1.6
ROUND_HALF_EVEN:同樣以5為分界線,如果是5,則前一位變偶數1.15->1.2 1.16->1.2 1.25->1.2 1.26->1.3
ROUND_HALF_UP:最常見的四舍五入
ROUND_UNNECESSARY:無需舍位
ROUND_UP:與ROUND_DOWN,遠離0的方向1.1->2 1.5->2 1.8->2 -1.1->-2 -1.5->-2 -1.8->-2
具體精確到幾位因該采用
商=被除數.devide(除數,保留小數位數,精確方法)
第三版
BigDecimal 由任意精度的整數非標度值 和 32 位的整數標度 (scale) 組成。如果為零或正數,則標度是小數點后的位數。如果為負數,則將該數的非標度值乘以 10 的負 scale 次冪。因此,BigDecimal 表示的數值是 (unscaledValue × 10-scale)。
可以處理任意長度的浮點數運算。
BigDecimal add(BigDecimal val) //BigDecimal 加法
BigDecimal subtract (BigDecimal val) //BigDecimal 減法
BigDecimal multiply (BigDecimal val) //BigDecimal 乘法
BigDecimal divide (BigDecimal val,RoundingMode mode) 除法
具體使用 計算:
加: a.add(b);
減: a.subtract(b);
乘: a.multiply(b);
除: a.divide(b,2);//2為精度取值
除法細解:
//注意以下相除會拋出異常,原因: 通過BigDecimal的divide方法進行除法時當不整除,出現無限循環小數時,就會拋異常
//BigDecimal divideBg = a.divide(b);
//解決方法是:設置精確度;就是給divide設置精確的小數點
divide(xxxxx,2, BigDecimal.ROUND_HALF_EVEN)
//其中的第二個參數表示的是:保留小數點之后多少位
BigDecimal不整除拋出的異常,請設置精確度!
Exception in thread "main" java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
at java.math.BigDecimal.divide(BigDecimal.java:1278)
at main.Main.main(Main.java:41)
下面我們來看看除法的詳細說明:
divide(BigDecimal divisor, int scale, introundingMode)
BigDecimal的setScale方法
BigDecimal.setScale()
方法用於格式化小數點
表示保留一位小數,默認用四舍五入方式
setScale(1)
直接刪除多余的小數位,如2.35會變成2.3 setScale(1,BigDecimal.ROUND_DOWN)
進位處理,2.35變成2.4 setScale(1,BigDecimal.ROUND_UP)
四舍五入,2.35變成2.4 setScale(1,BigDecimal.ROUND_HALF_UP)
四舍五入,2.35變成2.3,如果是5則向下舍setScaler(1,BigDecimal.ROUND_HALF_DOWN)
注意點一
scale指的是你小數點后的位數。
scale()就是BigDecimal類中的方法。如
BigDecimal b = new BigDecimal("123.456");
b.scale()返回的就是3
注意點二roundingMode是小數的保留模式。它們都是BigDecimal中的常量字段,
有很多種,如
BigDecimal.ROUND_HALF_UP表示的就是4舍5入
注意點三
divide(BigDecimal divisor, int scale, introundingMode)的意思是說:
我用一個BigDecimal對象除以divisor后的結果,並且要求這個結果保留有scale個小數位,roundingMode表示的就是保留模式是什么,是四舍五入啊還是其它的
BigDecimal aa = new BigDecimal(135.95 );
BigDecimal bb=new BigDecimal("100" );
BigDecimal result=aa.multiply(bb); //做加法
3.java中 BigDecimal類型的可以轉換到double類型:
用 變量.doubleValue();函數 即可將 BigDecimal 類型數據 轉化為 double類型!
4.java BigDecimal比較大小
可以通過BigDecimal的compareTo方法來進行比較。
返回的結果是int類型,-1表示小於,0是等於,1是大於。
看下面這個例子:
BigDecimal a = new BigDecimal("1.00");
BigDecmial b = new BigDecimal(1);
想比較一下a和b的大小,一般都會用equals
System.out.println(a.equals(b));
但是輸出結果是:false
原因是:BigDecimal比較時,不僅比較值,而且還比較精度?
if(a.compareTo(b)==0) 結果是true
比較大小可以用 a.compareTo(b)
返回值 -1 小於 0 等於 1 大於
5.BigDecimal取其中最大、最小值、絕對值、相反數:
a.max (b) //比較取最大值
a.min(b) //比較取最小值
a.abs()//取最絕對值
a.negate()//取相反數
6.下面是注意 :
BigDecimal枚舉常量用法摘要 :
CEILING
向正無限大方向舍入的舍入模式。
DOWN
向零方向舍入的舍入模式。
FLOOR
向負無限大方向舍入的舍入模式。
HALF_DOWN
向最接近數字方向舍入的舍入模式,如果與兩個相鄰數字的距離相等,則向下舍入。
HALF_EVEN
向最接近數字方向舍入的舍入模式,如果與兩個相鄰數字的距離相等,則向相鄰的偶數舍入。
HALF_UP
向最接近數字方向舍入的舍入模式,如果與兩個相鄰數字的距離相等,則向上舍入。
UNNECESSARY
用於斷言請求的操作具有精確結果的舍入模式,因此不需要舍入。
UP
遠離零方向舍入的舍入模式。
7.關於BigDecimal格式化
public String formatValue(Object value){
String content = null;
if (value == null) {
content = "";
} else {
if(value instanceof BigDecimal){
//conver to fortmat String
NumberFormat nf = NumberFormat.getInstance();
nf.setMinimumFractionDigits(2);
nf.setMaximumFractionDigits(2);
content = nf.format(value);
}else{
content = String.valueOf(value);
}
}
return content;
}
使用這樣一個方法可以達到格式化的效果,其中value instanceof BigDecimal,表示的是字符類型是BigDecimal類型的時候執行,這里的NumberFormat就表示字符類型,下面的兩句代碼就表示小數點后面的精確位數。
這里還要提到NumberFormat的其他兩個類型:
getCurrencyInstance(): 返回當前默認 環境的貨幣格式
CurrencyInstance(): 返回指定語言 環境的數字格式,一般是百分比格式
8.在《Effective Java》這本書中也提到這個原則,float和double只能用來做科學計算或者是工程計算,在商業計算中我們要用java.math.BigDecimal。
我們如果需要精確計算,非要用String來夠造BigDecimal不可!
下面的這個工具類是是轉載別人的,可以通過個工具類實現小數的精確計算。
1import java.math.BigDecimal;
2/** *//**
3* 由於Java的簡單類型不能夠精確的對浮點數進行運算,這個工具類提供精
4* 確的浮點數運算,包括加減乘除和四舍五入。
5*/
6public class Arith{
7 //默認除法運算精度
8 private static final int DEF_DIV_SCALE = 10;
9 //這個類不能實例化
10 private Arith(){
11 }
12
13 /** *//**
14 * 提供精確的加法運算。
15 * @param v1 被加數
16 * @param v2 加數
17 * @return 兩個參數的和
18 */
19 public static double add(double v1,double v2){
20 BigDecimal b1 = new BigDecimal(Double.toString(v1));
21 BigDecimal b2 = new BigDecimal(Double.toString(v2));
22 return b1.add(b2).doubleValue();
23 }
24 /** *//**
25 * 提供精確的減法運算。
26 * @param v1 被減數
27 * @param v2 減數
28 * @return 兩個參數的差
29 */
30 public static double sub(double v1,double v2){
31 BigDecimal b1 = new BigDecimal(Double.toString(v1));
32 BigDecimal b2 = new BigDecimal(Double.toString(v2));
33 return b1.subtract(b2).doubleValue();
34 }
35 /** *//**
36 * 提供精確的乘法運算。
37 * @param v1 被乘數
38 * @param v2 乘數
39 * @return 兩個參數的積
40 */
41 public static double mul(double v1,double v2){
42 BigDecimal b1 = new BigDecimal(Double.toString(v1));
43 BigDecimal b2 = new BigDecimal(Double.toString(v2));
44 return b1.multiply(b2).doubleValue();
45 }
46
47 /** *//**
48 * 提供(相對)精確的除法運算,當發生除不盡的情況時,精確到
49 * 小數點以后10位,以后的數字四舍五入。
50 * @param v1 被除數
51 * @param v2 除數
52 * @return 兩個參數的商
53 */
54 public static double div(double v1,double v2){
55 return div(v1,v2,DEF_DIV_SCALE);
56 }
57
58 /** *//**
59 * 提供(相對)精確的除法運算。當發生除不盡的情況時,由scale參數指
60 * 定精度,以后的數字四舍五入。
61 * @param v1 被除數
62 * @param v2 除數
63 * @param scale 表示表示需要精確到小數點以后幾位。
64 * @return 兩個參數的商
65 */
66 public static double div(double v1,double v2,int scale){
67 if(scale<0){
68 throw new IllegalArgumentException(
69 "The scale must be a positive integer or zero");
70 }
71 BigDecimal b1 = new BigDecimal(Double.toString(v1));
72 BigDecimal b2 = new BigDecimal(Double.toString(v2));
73 return b1.divid(b2,scale,BigDecimal.ROUND_HALF_UP).doubleValue();
74 }
75
76 /** *//**
77 * 提供精確的小數位四舍五入處理。
78 * @param v 需要四舍五入的數字
79 * @param scale 小數點后保留幾位
80 * @return 四舍五入后的結果
81 */
82 public static double round(double v,int scale){
83 if(scale<0){
84 throw new IllegalArgumentException(
85 "The scale must be a positive integer or zero");
86 }
87 BigDecimal b = new BigDecimal(Double.toString(v));
88 BigDecimal one = new BigDecimal("1");
89 return b.divid(one,scale,BigDecimal.ROUND_HALF_UP).doubleValue();
90 }
91 } BigDecimal 由任意精度的整數非標度值 和 32 位的整數標度 (scale) 組成。如果為零或正數,則標度是小數點后的位數。如果為負數,則將該數的非標度值乘以 10 的負 scale 次冪。因此,BigDecimal 表示的數值是 (unscaledValue × 10-scale)。
可以處理任意長度的浮點數運算。
BigDecimal add(BigDecimal val) //BigDecimal 加法
BigDecimal subtract (BigDecimal val) //BigDecimal 減法
BigDecimal multiply (BigDecimal val) //BigDecimal 乘法
BigDecimal divide (BigDecimal val,RoundingMode mode) 除法
具體使用 計算:
加: a.add(b);
減: a.subtract(b);
乘: a.multiply(b);
除: a.divide(b,2);//2為精度取值
除法細解:
//注意以下相除會拋出異常,原因: 通過BigDecimal的divide方法進行除法時當不整除,出現無限循環小數時,就會拋異常
//BigDecimal divideBg = a.divide(b);
//解決方法是:設置精確度;就是給divide設置精確的小數點
divide(xxxxx,2, BigDecimal.ROUND_HALF_EVEN)
//其中的第二個參數表示的是:保留小數點之后多少位
BigDecimal不整除拋出的異常,請設置精確度!
Exception in thread "main" java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
at java.math.BigDecimal.divide(BigDecimal.java:1278)
at main.Main.main(Main.java:41)
下面我們來看看除法的詳細說明:
divide(BigDecimal divisor, int scale, introundingMode)
BigDecimal的setScale方法
BigDecimal.setScale()
方法用於格式化小數點
表示保留一位小數,默認用四舍五入方式
setScale(1)
直接刪除多余的小數位,如2.35會變成2.3 setScale(1,BigDecimal.ROUND_DOWN)
進位處理,2.35變成2.4 setScale(1,BigDecimal.ROUND_UP)
四舍五入,2.35變成2.4 setScale(1,BigDecimal.ROUND_HALF_UP)
四舍五入,2.35變成2.3,如果是5則向下舍setScaler(1,BigDecimal.ROUND_HALF_DOWN)
注意點一
scale指的是你小數點后的位數。
scale()就是BigDecimal類中的方法。如
BigDecimal b = new BigDecimal("123.456");
b.scale()返回的就是3
注意點二roundingMode是小數的保留模式。它們都是BigDecimal中的常量字段,
有很多種,如
BigDecimal.ROUND_HALF_UP表示的就是4舍5入
注意點三
divide(BigDecimal divisor, int scale, introundingMode)的意思是說:
我用一個BigDecimal對象除以divisor后的結果,並且要求這個結果保留有scale個小數位,roundingMode表示的就是保留模式是什么,是四舍五入啊還是其它的
BigDecimal aa = new BigDecimal(135.95 );
BigDecimal bb=new BigDecimal("100" );
BigDecimal result=aa.multiply(bb); //做加法
3.java中 BigDecimal類型的可以轉換到double類型:
用 變量.doubleValue();函數 即可將 BigDecimal 類型數據 轉化為 double類型!
4.java BigDecimal比較大小
可以通過BigDecimal的compareTo方法來進行比較。
返回的結果是int類型,-1表示小於,0是等於,1是大於。
看下面這個例子:
BigDecimal a = new BigDecimal("1.00");
BigDecmial b = new BigDecimal(1);
想比較一下a和b的大小,一般都會用equals
System.out.println(a.equals(b));
但是輸出結果是:false
原因是:BigDecimal比較時,不僅比較值,而且還比較精度?
if(a.compareTo(b)==0) 結果是true
比較大小可以用 a.compareTo(b)
返回值 -1 小於 0 等於 1 大於
5.BigDecimal取其中最大、最小值、絕對值、相反數:
a.max (b) //比較取最大值
a.min(b) //比較取最小值
a.abs()//取最絕對值
a.negate()//取相反數
6.下面是注意 :
BigDecimal枚舉常量用法摘要 :
CEILING
向正無限大方向舍入的舍入模式。
DOWN
向零方向舍入的舍入模式。
FLOOR
向負無限大方向舍入的舍入模式。
HALF_DOWN
向最接近數字方向舍入的舍入模式,如果與兩個相鄰數字的距離相等,則向下舍入。
HALF_EVEN
向最接近數字方向舍入的舍入模式,如果與兩個相鄰數字的距離相等,則向相鄰的偶數舍入。
HALF_UP
向最接近數字方向舍入的舍入模式,如果與兩個相鄰數字的距離相等,則向上舍入。
UNNECESSARY
用於斷言請求的操作具有精確結果的舍入模式,因此不需要舍入。
UP
遠離零方向舍入的舍入模式。
7.關於BigDecimal格式化
public String formatValue(Object value){
String content = null;
if (value == null) {
content = "";
} else {
if(value instanceof BigDecimal){
//conver to fortmat String
NumberFormat nf = NumberFormat.getInstance();
nf.setMinimumFractionDigits(2);
nf.setMaximumFractionDigits(2);
content = nf.format(value);
}else{
content = String.valueOf(value);
}
}
return content;
}
使用這樣一個方法可以達到格式化的效果,其中value instanceof BigDecimal,表示的是字符類型是BigDecimal類型的時候執行,這里的NumberFormat就表示字符類型,下面的兩句代碼就表示小數點后面的精確位數。
這里還要提到NumberFormat的其他兩個類型:
getCurrencyInstance(): 返回當前默認 環境的貨幣格式
CurrencyInstance(): 返回指定語言 環境的數字格式,一般是百分比格式
8.在《Effective Java》這本書中也提到這個原則,float和double只能用來做科學計算或者是工程計算,在商業計算中我們要用java.math.BigDecimal。
我們如果需要精確計算,非要用String來夠造BigDecimal不可!
下面的這個工具類是是轉載別人的,可以通過個工具類實現小數的精確計算。
1import java.math.BigDecimal;
2/** *//**
3* 由於Java的簡單類型不能夠精確的對浮點數進行運算,這個工具類提供精
4* 確的浮點數運算,包括加減乘除和四舍五入。
5*/
6public class Arith{
7 //默認除法運算精度
8 private static final int DEF_DIV_SCALE = 10;
9 //這個類不能實例化
10 private Arith(){
11 }
12
13 /** *//**
14 * 提供精確的加法運算。
15 * @param v1 被加數
16 * @param v2 加數
17 * @return 兩個參數的和
18 */
19 public static double add(double v1,double v2){
20 BigDecimal b1 = new BigDecimal(Double.toString(v1));
21 BigDecimal b2 = new BigDecimal(Double.toString(v2));
22 return b1.add(b2).doubleValue();
23 }
24 /** *//**
25 * 提供精確的減法運算。
26 * @param v1 被減數
27 * @param v2 減數
28 * @return 兩個參數的差
29 */
30 public static double sub(double v1,double v2){
31 BigDecimal b1 = new BigDecimal(Double.toString(v1));
32 BigDecimal b2 = new BigDecimal(Double.toString(v2));
33 return b1.subtract(b2).doubleValue();
34 }
35 /** *//**
36 * 提供精確的乘法運算。
37 * @param v1 被乘數
38 * @param v2 乘數
39 * @return 兩個參數的積
40 */
41 public static double mul(double v1,double v2){
42 BigDecimal b1 = new BigDecimal(Double.toString(v1));
43 BigDecimal b2 = new BigDecimal(Double.toString(v2));
44 return b1.multiply(b2).doubleValue();
45 }
46
47 /** *//**
48 * 提供(相對)精確的除法運算,當發生除不盡的情況時,精確到
49 * 小數點以后10位,以后的數字四舍五入。
50 * @param v1 被除數
51 * @param v2 除數
52 * @return 兩個參數的商
53 */
54 public static double div(double v1,double v2){
55 return div(v1,v2,DEF_DIV_SCALE);
56 }
57
58 /** *//**
59 * 提供(相對)精確的除法運算。當發生除不盡的情況時,由scale參數指
60 * 定精度,以后的數字四舍五入。
61 * @param v1 被除數
62 * @param v2 除數
63 * @param scale 表示表示需要精確到小數點以后幾位。
64 * @return 兩個參數的商
65 */
66 public static double div(double v1,double v2,int scale){
67 if(scale<0){
68 throw new IllegalArgumentException(
69 "The scale must be a positive integer or zero");
70 }
71 BigDecimal b1 = new BigDecimal(Double.toString(v1));
72 BigDecimal b2 = new BigDecimal(Double.toString(v2));
73 return b1.divid(b2,scale,BigDecimal.ROUND_HALF_UP).doubleValue();
74 }
75
76 /** *//**
77 * 提供精確的小數位四舍五入處理。
78 * @param v 需要四舍五入的數字
79 * @param scale 小數點后保留幾位
80 * @return 四舍五入后的結果
81 */
82 public static double round(double v,int scale){
83 if(scale<0){
84 throw new IllegalArgumentException(
85 "The scale must be a positive integer or zero");
86 }
87 BigDecimal b = new BigDecimal(Double.toString(v));
88 BigDecimal one = new BigDecimal("1");
89 return b.divid(one,scale,BigDecimal.ROUND_HALF_UP).doubleValue();
90 }
91 }