目录
1. BigDecimal 为不可变对象 , 每次“操作”都会返回新对象
2. [精度] precision、[非标度值] unscale、[标度] scale
1. BigD~支持任意精度 , 任意长度的浮点数运算 ( 建议设精确度 )
5. BigDecimal 总结 - ★★★
BigDecimal总结_gqltt的博客-CSDN博客_bigdecimal的decimal32
1. BigDecimal 为不可变对象 , 每次“操作”都会返回新对象
1. BigDecimal 源码 API【概念】
通过查看 BigDecimal
源码API所知:
java.math.BigDecimal
不可变的、任意精度的有符号十进制数。BigDecimal 由任意精度的整数非标度值和32位的整数标度(scale)组成。
如果为零或正数 , 则标度是小数点后的位数。如果为负数 , 则将该数的非标度值乘以10的负scale次幂。
因此 , BigDecimal 表示的数值是 ( unscaledValue × 10-scale
) 。
与之相关的还有两个类:
java.math.MathContext:
该对象是封装上下文设置的不可变对象 , 它描述数字运算符的某些规则 , 如数据的精度 , 舍入方式等。
java.math.RoundingMode:
这是一种枚举类型 , 定义了很多常用的数据舍入方式。
这个类用起来还是很比较复杂的 , 原因在于舍入模式 , 数据运算规则太多太多 ,
不是数学专业出身的人看着中文API都难以理解 , 这些规则在实际中使用的时候在翻阅都来得及。
应用场景:
在银行、帐户、计费等领域 , BigDecimal 提供了精确的数值计算。其中8种舍入方式值得掌握。
2. [精度] precision、[非标度值] unscale、[标度] scale
//-------- 正数的[精度]precision、[非标度值]unscale、[标度]scale
// 0 precision=1 , unscale=0 , scale=0
BigDecimal tmp = new BigDecimal("0");
System.out.println( "0 precision=" + tmp.precision() +" , unscale=" + tmp.unscaledValue()+ " , scale=" + tmp.scale() );
tmp = new BigDecimal("0.0");
//0.0 precision=1 , unscale=0 , scale=1
System.out.println( "0.0 precision=" + tmp.precision() +" , unscale=" + tmp.unscaledValue()+ " , scale=" + tmp.scale());
tmp = new BigDecimal("1");
//1 precision=1 , unscale=1 , scale=0
System.out.println( "1 precision=" + tmp.precision() +" , unscale=" + tmp.unscaledValue()+ " , scale=" + tmp.scale());
tmp = new BigDecimal("1.0");
//1.0 precision=2 , unscale=10 , scale=1
System.out.println( "1.0 precision=" + tmp.precision() +" , unscale=" + tmp.unscaledValue()+ " , scale=" + tmp.scale());
tmp = new BigDecimal("0.1");
//0.1 precision=1 , unscale=1 , scale=1
System.out.println( "0.1 precision=" + tmp.precision() +" , unscale=" + tmp.unscaledValue()+ " , scale=" + tmp.scale());
tmp = new BigDecimal("122.000");
//122.000 precision=6 , unscale=122000 , scale=3
System.out.println( "122.000 precision=" + tmp.precision() +" , unscale=" + tmp.unscaledValue()+ " , scale=" + tmp.scale());
//----------负数的[精度]precision、[非标度值]unscale、[标度]scale
//-0 precision=1 , unscale=0 , scale=0
tmp = new BigDecimal("-0");
System.out.println( "-0 precision=" + tmp.precision() +" , unscale=" + tmp.unscaledValue()+ " , scale=" + tmp.scale() );
tmp = new BigDecimal("-0.0");
//-0.0 precision=1 , unscale=0 , scale=1
System.out.println( "-0.0 precision=" + tmp.precision() +" , unscale=" + tmp.unscaledValue()+ " , scale=" + tmp.scale());
tmp = new BigDecimal("-1");
//-1 precision=1 , unscale=-1 , scale=0
System.out.println( "-1 precision=" + tmp.precision() +" , unscale=" + tmp.unscaledValue()+ " , scale=" + tmp.scale());
tmp = new BigDecimal("-1.0");
//-1.0 precision=2 , unscale=-10 , scale=1
System.out.println( "-1.0 precision=" + tmp.precision() +" , unscale=" + tmp.unscaledValue()+ " , scale=" + tmp.scale());
tmp = new BigDecimal("-0.1");
//-0.1 precision=1 , unscale=-1 , scale=1
System.out.println( "-0.1 precision=" + tmp.precision() +" , unscale=" + tmp.unscaledValue()+ " , scale=" + tmp.scale());
tmp = new BigDecimal("-122.000");
//-122.000 precision=6 , unscale=-122000 , scale=3
System.out.println( "-122.000 precision=" + tmp.precision() +" , unscale=" + tmp.unscaledValue()+ " , scale=" + tmp.scale());
1. BigD~支持任意精度 , 任意长度的浮点数运算 ( 建议设精确度 )
BigDecimal 支持任意精度 , 任意长度的浮点数运算 , 但在运算的时候最好设置各个操作数的小数精确度 , 特别是除法。
结果需要保留几位小数 , 如果没有设置除法的操作数的小数精确度 , 计算结果的精确度就会和操作数中最低精确度一致 , 导致计算结果不正确 ,
如下例子:
String a = "1";
String b = "4.56";
BigDecimal aBD = new BigDecimal(a);
BigDecimal bBD = new BigDecimal(b);
BigDecimal resultBD = aBD.divide(bBD).setScale(3 , java.math.BigDecimal.ROUND_HALF_UP);
3是保留小数 , ROUND_HALF_UP是四舍五入 , 此参数的其他值请查看文章:http://www.bdqn.cn/news/201311/11834.shtml
这个例子你期望的是0.219 , 但是你实际会得到0。
为什么呢?
这就是保留精确度问题了 , a是一个整数 , 运算时把结果当作整数取了 , 那就是0了。
所以 , 应该按下面的运算:
String a = "1";
String b = "4.56";
BigDecimal aBD = new BigDecimal(a).setScale(3);
BigDecimal bBD = new BigDecimal(b).setScale(3);
BigDecimal resultBD = aBD.divide(bBD).setScale(3 , java.math.BigDecimal.ROUND_HALF_UP);
这样 , 你就会得到一个正确的值了。
还有一个需要注意的点 , 计算结果 , 如例子中的resultBD一定要设置其setScale的第二个参数 , 不然会报错。
如果计算结果没有按某个方式进行截断 , 那么机器就不知道如何去取这个结果了 , 因此报错。
3. 强制设置[标度] scale
//强制设置[标度]scale
//----scale默认的0设置为3
BigDecimal de1 = new BigDecimal("125");
System.out.println( "默认scale为0:" + de1 );
System.out.println( "强制设置scale为3:" + de1.setScale(3) );
//----scale由初始的2设置为5
de1 = new BigDecimal("28.02");
System.out.println( "初始scale为2:" + de1 );
System.out.println( "强制设置scale为5:" + de1.setScale(5) );
//----scale由初始的7设置为2
de1 = new BigDecimal("177.1234567");
System.out.println( "初始scale为7:" + de1 );
try{
//精度由大变小(7->2)必须设置舍入规则
System.out.println( "强制设置scale为2:" + de1.setScale(2) );
}catch(Exception e){
System.out.println( e.getMessage() );
}
System.out.println( "强制设置scale为2:" + de1.setScale(2 , RoundingMode.HALF_UP) );
4. 舍入 : 详细示例
BigDecimal b1 = new BigDecimal("1");
BigDecimal b2 = new BigDecimal("2");
BigDecimal b3 = new BigDecimal("3");
//按指定精度 , 向上0.333∞ -> 1
System.out.println("ROUND_CEILING:1/3 = " + b1.divide(b3 , RoundingMode.CEILING) );
//按指定精度 , 向上0.333∞ -> 1
System.out.println("ROUND_UP:1/3 = " + b1.divide(b3 , RoundingMode.UP) );
//按指定精度 , 向下0.333∞ -> 0
System.out.println("ROUND_DOWN:1/3 = " + b1.divide(b3 , RoundingMode.DOWN) );
//按指定精度 , 向下0.333∞ -> 0
System.out.println("ROUND_FLOOR:1/3 = " + b1.divide(b3 , RoundingMode.FLOOR) );
//按指定精度 , 趋近最近的数 , 0.333∞ -> 0
System.out.println("ROUND_HALF_DOWN:1/3 = " + b1.divide(b3 , RoundingMode.HALF_DOWN) );
//按指定精度 , 趋近最近的数 , 0.333∞ -> 0
System.out.println("ROUND_HALF_UP:1/3 = " + b1.divide(b3 , RoundingMode.HALF_UP) );
//按指定精度 , 趋近最近的数 , 0.5向下 0.5-> 0
System.out.println("ROUND_HALF_DOWN:1/2 = " + b1.divide(b2 , RoundingMode.HALF_DOWN) );
//按指定精度 , 趋近最近的数 , 0.5向上 0.5-> 1
System.out.println("ROUND_HALF_UP:1/2 = " + b1.divide(b2 , RoundingMode.HALF_UP) );
//按指定精度 , 趋近最近的数 , 0.333∞ -> 1
System.out.println("ROUND_HALF_DOWN:2/3 = " + b2.divide(b3 , RoundingMode.HALF_DOWN) );
//按指定精度 , 趋近最近的数 , 0.333∞ -> 1
System.out.println("ROUND_HALF_UP:2/3 = " + b2.divide(b3 , RoundingMode.HALF_UP) );
//按指定精度 , 趋近最近的数 , 0.5 -> 偶数
//ROUND_HALF_EVEN:1/3 = 0
System.out.println("ROUND_HALF_EVEN:1/3 = " + b1.divide(b3 , RoundingMode.HALF_EVEN) );
//ROUND_HALF_EVEN:1/2 = 0
System.out.println("ROUND_HALF_EVEN:1/2 = " + b1.divide(b2 , RoundingMode.HALF_EVEN) );
//ROUND_HALF_EVEN:2/3 = 1
System.out.println("ROUND_HALF_EVEN:2/3 = " + b2.divide(b3 , RoundingMode.HALF_EVEN) );
//明确知道结果 , 否则抛异常
System.out.println("ROUND_UNNECESSARY:2 = " + b2.setScale(2 , RoundingMode.UNNECESSARY));
try{
//计算中的结果无法使用:ROUND_UNNECESSARY
System.out.println("ROUND_UNNECESSARY:1/2 = " + b1.divide(b2 , RoundingMode.UNNECESSARY) );
}catch( Exception e ){
//Rounding necessary
System.out.println( e.getMessage() );
}
1. 舍入方式值 ( 8 种 )
1、ROUND_UP
舍入远离零的舍入模式。
在丢弃非零部分之前始终增加数字(始终对非零舍弃部分前面的数字加1)。
注意 , 此舍入模式始终不会减少计算值的大小。
2、ROUND_DOWN
接近零的舍入模式。
在丢弃某部分之前始终不增加数字(从不对舍弃部分前面的数字加1 , 即截短)。
注意 , 此舍入模式始终不会增加计算值的大小。
3、ROUND_CEILING
接近正无穷大的舍入模式。
如果 BigDecimal 为正 , 则舍入行为与 ROUND_UP 相同;
如果为负 , 则舍入行为与 ROUND_DOWN 相同。
注意 , 此舍入模式始终不会减少计算值。
4、ROUND_FLOOR
接近负无穷大的舍入模式。
如果 BigDecimal 为正 , 则舍入行为与 ROUND_DOWN 相同;
如果为负 , 则舍入行为与 ROUND_UP 相同。
注意 , 此舍入模式始终不会增加计算值。
5、ROUND_HALF_UP
向“最接近的”数字舍入 , 如果与两个相邻数字的距离相等 , 则为向上舍入的舍入模式。
如果舍弃部分 >= 0.5 , 则舍入行为与 ROUND_UP 相同;否则舍入行为与 ROUND_DOWN 相同。
注意 , 这是我们大多数人在小学时就学过的舍入模式(四舍五入)。
6、ROUND_HALF_DOWN
向“最接近的”数字舍入 , 如果与两个相邻数字的距离相等 , 则为上舍入的舍入模式。
如果舍弃部分 > 0.5 , 则舍入行为与 ROUND_UP 相同;否则舍入行为与 ROUND_DOWN 相同(五舍六入)。
7、ROUND_HALF_EVEN
向“最接近的”数字舍入 , 如果与两个相邻数字的距离相等 , 则向相邻的偶数舍入。
如果舍弃部分左边的数字为奇数 , 则舍入行为与 ROUND_HALF_UP 相同;
如果为偶数 , 则舍入行为与 ROUND_HALF_DOWN 相同。
注意 , 在重复进行一系列计算时 , 此舍入模式可以将累加错误减到最小。
此舍入模式也称为“银行家舍入法” , 主要在美国使用。四舍六入 , 五分两种情况。
如果前一位为奇数 , 则入位 , 否则舍去。
以下例子为保留小数点1位 , 那么这种舍入方式下的结果。
1.15>1.2 1.25>1.2
8、ROUND_UNNECESSARY
断言请求的操作具有精确的结果 , 因此不需要舍入。
如果对获得精确结果的操作指定此舍入模式 , 则抛出 ArithmeticException。
2. 不同舍入模式下的舍入操作汇总
根据给定的舍入模式将输入数字舍入为一位数的结果
输入数字 UP DOWN CEILING FLOOR HALF_UP HALF_DOWN HALF_EVEN UNNECESSARY
5.5 6 5 6 5 6 5 6 抛出 ArithmeticException
2.5 3 2 3 2 3 2 2 抛出 ArithmeticException
1.6 2 1 2 1 2 2 2 抛出 ArithmeticException
1.1 2 1 2 1 1 1 1 抛出 ArithmeticException
1.0 1 1 1 1 1 1 1 1 -1.0 -1 -1 -1 -1 -1 -1 -1 -1 -1.1 -2 -1 -1 -2 -1 -1 -1 抛出 ArithmeticException
-1.6 -2 -1 -1 -2 -2 -2 -2 抛出 ArithmeticException
-2.5 -3 -2 -2 -3 -3 -2 -2 抛出 ArithmeticException
-5.5 -6 -5 -5 -6 -6 -5 -6 抛出 ArithmeticException
5. MathContext 示例
//计算数的位数较小 , 最后结果都一样
BigDecimal b1 = new BigDecimal( "23.323" );
BigDecimal b2 = new BigDecimal( "323.57" );
//346.893 precision=6 , unscale=346893 , scale=3
info( b1.add(b2 , MathContext.DECIMAL32) );
//346.893 precision=6 , unscale=346893 , scale=3
info( b1.add(b2 , MathContext.DECIMAL64) );
//346.893 precision=6 , unscale=346893 , scale=3
info( b1.add(b2 , MathContext.DECIMAL128) );
//DECIMAL32-->precision最大为7
//DECIMAL64-->precision最大为16
//DECIMAL128-->precision最大为34
b1 = new BigDecimal( "1231243434341223.25532323" );
b2 = new BigDecimal( "4532323.55457" );
//1.231243E+15 precision=7 , unscale=1231243 , scale=-9
info( b1.add(b2 , MathContext.DECIMAL32) );
//1231243438873547 precision=16 , unscale=1231243438873547 , scale=0
info( b1.add(b2 , MathContext.DECIMAL64) );
//1231243438873546.80989323 precision=24 , unscale=123124343887354680989323 , scale=8
info( b1.add(b2 , MathContext.DECIMAL128) );
6. equals 和 sort
注:如果 BigDecimal 对象用作 SortedMap 中的键或 SortedSet 中的元素 , 则应特别小心 , 因为 BigDecimal 的自然排序与 equals 方法不一致。
Map接口是按照 equals 操作定义的 , 但有序映射SortedMap使用它的 compareTo(或 compare)方法对所有键进行比较
BigDecimal b1 = new BigDecimal("28.000");
BigDecimal b2 = new BigDecimal(28);
//28.000 precision=5 , unscale=28000 , scale=3
info( b1 );
//28 precision=2 , unscale=28 , scale=0
info( b2 );
//false
System.out.println( b1.equals(b2) );
System.out.println( "b1.hashCode=" + b1.hashCode() );
System.out.println( "b2.hashCode=" + b2.hashCode() );
//0
System.out.println( b1.compareTo(b2) );
//注:如果 BigDecimal 对象用作 SortedMap 中的键或 SortedSet 中的元素 , 则应特别小心 , 因为 BigDecimal 的自然排序与 equals 方法不一致。
Map<BigDecimal , String> treeMap = new TreeMap<BigDecimal , String>();
treeMap.put(b1 , "28.000");
treeMap.put(b2 , "28");
treeMap.put(new BigDecimal("12") , "12");
//{12=12 , 28.000=28}
System.out.println( treeMap );
Map<BigDecimal , String> hashMap = new HashMap<BigDecimal , String>();
hashMap.put(b1 , "28.000");
hashMap.put(b2 , "28");
hashMap.put(new BigDecimal("12") , "12");
//{28.000=28.000 , 12=12 , 28=28}
System.out.println( hashMap );
// Map接口是按照 equals 操作定义的 , 但有序映射SortedMap使用它的 compareTo(或 compare)方法对所有键进行比较
7. 综合示例
static void actionByDouble(){
String[] arr = new String[]{"3649926.00" , "213582.00" , "253270.00" ,
"172841.00" , "204571.00" , "177974.00" , "189629.00" , "155114.00" ,
"135878.00" , "119562.00" , "132559.00" , "159562.00" , "161837.00" ,
"103169.00" , "136250.00" , "132953.00" , "121470.00000000001"};
BigDecimal total = BigDecimal.ZERO;
for( String s : arr ){
double d = Double.valueOf(s);
BigDecimal num = new BigDecimal(d);
total = total.add( num );
}
//actionByDouble: total=6220147.00
System.out.println( "actionByDouble: total=" + total.setScale(2 , BigDecimal.ROUND_HALF_UP) );
}
1. BigDecimalTest.java
public class BigDecimalTest {
/**
* @param args
*/
public static void main(final String[] args) {
actionByString();
actionByDouble();
test();
matchContext();
equalsAndSort();
}
static void test(){
//正数的[精度]precision、[非标度值]unscale、[标度]scale
//0 precision=1 , unscale=0 , scale=0
BigDecimal tmp = new BigDecimal("0");
System.out.println( "0 precision=" + tmp.precision() +" , unscale=" + tmp.unscaledValue()+ " , scale=" + tmp.scale() );
tmp = new BigDecimal("0.0");
//0.0 precision=1 , unscale=0 , scale=1
System.out.println( "0.0 precision=" + tmp.precision() +" , unscale=" + tmp.unscaledValue()+ " , scale=" + tmp.scale());
tmp = new BigDecimal("1");
//1 precision=1 , unscale=1 , scale=0
System.out.println( "1 precision=" + tmp.precision() +" , unscale=" + tmp.unscaledValue()+ " , scale=" + tmp.scale());
tmp = new BigDecimal("1.0");
//1.0 precision=2 , unscale=10 , scale=1
System.out.println( "1.0 precision=" + tmp.precision() +" , unscale=" + tmp.unscaledValue()+ " , scale=" + tmp.scale());
tmp = new BigDecimal("0.1");
//0.1 precision=1 , unscale=1 , scale=1
System.out.println( "0.1 precision=" + tmp.precision() +" , unscale=" + tmp.unscaledValue()+ " , scale=" + tmp.scale());
tmp = new BigDecimal("122.000");
//122.000 precision=6 , unscale=122000 , scale=3
System.out.println( "122.000 precision=" + tmp.precision() +" , unscale=" + tmp.unscaledValue()+ " , scale=" + tmp.scale());
//----------负数的[精度]precision、[非标度值]unscale、[标度]scale
//-0 precision=1 , unscale=0 , scale=0
tmp = new BigDecimal("-0");
System.out.println( "-0 precision=" + tmp.precision() +" , unscale=" + tmp.unscaledValue()+ " , scale=" + tmp.scale() );
tmp = new BigDecimal("-0.0");
//-0.0 precision=1 , unscale=0 , scale=1
System.out.println( "-0.0 precision=" + tmp.precision() +" , unscale=" + tmp.unscaledValue()+ " , scale=" + tmp.scale());
tmp = new BigDecimal("-1");
//-1 precision=1 , unscale=-1 , scale=0
System.out.println( "-1 precision=" + tmp.precision() +" , unscale=" + tmp.unscaledValue()+ " , scale=" + tmp.scale());
tmp = new BigDecimal("-1.0");
//-1.0 precision=2 , unscale=-10 , scale=1
System.out.println( "-1.0 precision=" + tmp.precision() +" , unscale=" + tmp.unscaledValue()+ " , scale=" + tmp.scale());
tmp = new BigDecimal("-0.1");
//-0.1 precision=1 , unscale=-1 , scale=1
System.out.println( "-0.1 precision=" + tmp.precision() +" , unscale=" + tmp.unscaledValue()+ " , scale=" + tmp.scale());
tmp = new BigDecimal("-122.000");
//-122.000 precision=6 , unscale=-122000 , scale=3
System.out.println( "-122.000 precision=" + tmp.precision() +" , unscale=" + tmp.unscaledValue()+ " , scale=" + tmp.scale());
//强制设置[标度]scale
//----scale默认的0设置为3
BigDecimal de1 = new BigDecimal("125");
System.out.println( "默认scale为0:" + de1 );
System.out.println( "强制设置scale为3:" + de1.setScale(3) );
//----scale由初始的2设置为5
de1 = new BigDecimal("28.02");
System.out.println( "初始scale为2:" + de1 );
System.out.println( "强制设置scale为5:" + de1.setScale(5) );
//----scale由初始的7设置为2
de1 = new BigDecimal("177.1234567");
System.out.println( "初始scale为7:" + de1 );
try{
//精度由大变小(7->2)必须设置舍入规则
System.out.println( "强制设置scale为2:" + de1.setScale(2) );
}catch(Exception e){
System.out.println( e.getMessage() );
}
System.out.println( "强制设置scale为2:" + de1.setScale(2 , RoundingMode.HALF_UP) );
BigDecimal b1 = new BigDecimal("1");
BigDecimal b2 = new BigDecimal("2");
BigDecimal b3 = new BigDecimal("3");
//按指定精度 , 向上0.333∞ -> 1
System.out.println("ROUND_CEILING:1/3 = " + b1.divide(b3 , RoundingMode.CEILING) );
//按指定精度 , 向上0.333∞ -> 1
System.out.println("ROUND_UP:1/3 = " + b1.divide(b3 , RoundingMode.UP) );
//按指定精度 , 向下0.333∞ -> 0
System.out.println("ROUND_DOWN:1/3 = " + b1.divide(b3 , RoundingMode.DOWN) );
//按指定精度 , 向下0.333∞ -> 0
System.out.println("ROUND_FLOOR:1/3 = " + b1.divide(b3 , RoundingMode.FLOOR) );
//按指定精度 , 趋近最近的数 , 0.333∞ -> 0
System.out.println("ROUND_HALF_DOWN:1/3 = " + b1.divide(b3 , RoundingMode.HALF_DOWN) );
//按指定精度 , 趋近最近的数 , 0.333∞ -> 0
System.out.println("ROUND_HALF_UP:1/3 = " + b1.divide(b3 , RoundingMode.HALF_UP) );
//按指定精度 , 趋近最近的数 , 0.5向下 0.5-> 0
System.out.println("ROUND_HALF_DOWN:1/2 = " + b1.divide(b2 , RoundingMode.HALF_DOWN) );
//按指定精度 , 趋近最近的数 , 0.5向上 0.5-> 1
System.out.println("ROUND_HALF_UP:1/2 = " + b1.divide(b2 , RoundingMode.HALF_UP) );
//按指定精度 , 趋近最近的数 , 0.333∞ -> 1
System.out.println("ROUND_HALF_DOWN:2/3 = " + b2.divide(b3 , RoundingMode.HALF_DOWN) );
//按指定精度 , 趋近最近的数 , 0.333∞ -> 1
System.out.println("ROUND_HALF_UP:2/3 = " + b2.divide(b3 , RoundingMode.HALF_UP) );
//按指定精度 , 趋近最近的数 , 0.5 -> 偶数
//ROUND_HALF_EVEN:1/3 = 0
System.out.println("ROUND_HALF_EVEN:1/3 = " + b1.divide(b3 , RoundingMode.HALF_EVEN) );
//ROUND_HALF_EVEN:1/2 = 0
System.out.println("ROUND_HALF_EVEN:1/2 = " + b1.divide(b2 , RoundingMode.HALF_EVEN) );
//ROUND_HALF_EVEN:2/3 = 1
System.out.println("ROUND_HALF_EVEN:2/3 = " + b2.divide(b3 , RoundingMode.HALF_EVEN) );
//明确知道结果 , 否则抛异常
System.out.println("ROUND_UNNECESSARY:2 = " + b2.setScale(2 , RoundingMode.UNNECESSARY));
try{
//计算中的结果无法使用:ROUND_UNNECESSARY
System.out.println("ROUND_UNNECESSARY:1/2 = " + b1.divide(b2 , RoundingMode.UNNECESSARY) );
}catch( Exception e ){
//Rounding necessary
System.out.println( e.getMessage() );
}
}
static void matchContext(){
//计算数的位数较小 , 最后结果都一样
BigDecimal b1 = new BigDecimal( "23.323" );
BigDecimal b2 = new BigDecimal( "323.57" );
//346.893 precision=6 , unscale=346893 , scale=3
info( b1.add(b2 , MathContext.DECIMAL32) );
//346.893 precision=6 , unscale=346893 , scale=3
info( b1.add(b2 , MathContext.DECIMAL64) );
//346.893 precision=6 , unscale=346893 , scale=3
info( b1.add(b2 , MathContext.DECIMAL128) );
//DECIMAL32-->precision最大为7
//DECIMAL64-->precision最大为16
//DECIMAL128-->precision最大为34
b1 = new BigDecimal( "1231243434341223.25532323" );
b2 = new BigDecimal( "4532323.55457" );
//1.231243E+15 precision=7 , unscale=1231243 , scale=-9
info( b1.add(b2 , MathContext.DECIMAL32) );
//1231243438873547 precision=16 , unscale=1231243438873547 , scale=0
info( b1.add(b2 , MathContext.DECIMAL64) );
//1231243438873546.80989323 precision=24 , unscale=123124343887354680989323 , scale=8
info( b1.add(b2 , MathContext.DECIMAL128) );
}
static void equalsAndSort(){
BigDecimal b1 = new BigDecimal("28.000");
BigDecimal b2 = new BigDecimal(28);
//28.000 precision=5 , unscale=28000 , scale=3
info( b1 );
//28 precision=2 , unscale=28 , scale=0
info( b2 );
//false
System.out.println( b1.equals(b2) );
System.out.println( "b1.hashCode=" + b1.hashCode() );
System.out.println( "b2.hashCode=" + b2.hashCode() );
//0
System.out.println( b1.compareTo(b2) );
//注:如果 BigDecimal 对象用作 SortedMap 中的键或 SortedSet 中的元素 , 则应特别小心 , 因为 BigDecimal 的自然排序与 equals 方法不一致。
Map<BigDecimal , String> treeMap = new TreeMap<BigDecimal , String>();
treeMap.put(b1 , "28.000");
treeMap.put(b2 , "28");
treeMap.put(new BigDecimal("12") , "12");
//{12=12 , 28.000=28}
System.out.println( treeMap );
Map<BigDecimal , String> hashMap = new HashMap<BigDecimal , String>();
hashMap.put(b1 , "28.000");
hashMap.put(b2 , "28");
hashMap.put(new BigDecimal("12") , "12");
//{28.000=28.000 , 12=12 , 28=28}
System.out.println( hashMap );
// Map接口是按照 equals 操作定义的 , 但有序映射SortedMap使用它的 compareTo(或 compare)方法对所有键进行比较
}
static void actionByString(){
String[] arr = new String[]{"3649926.00" , "213582.00" , "253270.00" ,
"172841" , "204571" , "177974" , "189629" , "155114" ,
"135878" , "119562" , "132559" , "159562" , "161837" ,
"103169" , "136250" , "132953" , "121470.00000434"};
BigDecimal total = BigDecimal.ZERO;
for( String s : arr ){
BigDecimal num = new BigDecimal(s);
total = total.add( num );
}
//actionByString: total=6220147.00
System.out.println( "actionByString: total=" + total.setScale(2 , RoundingMode.HALF_UP) );
}
static void actionByDouble(){
String[] arr = new String[]{"3649926.00" , "213582.00" , "253270.00" ,
"172841.00" , "204571.00" , "177974.00" , "189629.00" , "155114.00" ,
"135878.00" , "119562.00" , "132559.00" , "159562.00" , "161837.00" ,
"103169.00" , "136250.00" , "132953.00" , "121470.00000000001"};
BigDecimal total = BigDecimal.ZERO;
for( String s : arr ){
double d = Double.valueOf(s);
BigDecimal num = new BigDecimal(d);
total = total.add( num );
}
//actionByDouble: total=6220147.00
System.out.println( "actionByDouble: total=" + total.setScale(2 , BigDecimal.ROUND_HALF_UP) );
}
/**
* 指定BigDecimal的内部信息
* @param decimal
*/
static void info( final BigDecimal decimal ){
System.out.println( decimal + " precision=" + decimal.precision() +" , unscale=" + decimal.unscaledValue()+ " , scale=" + decimal.scale());
}
}