BigDecimal总结

Java 专栏收录该内容
50 篇文章 0 订阅

1、BigDecimal为不可变对象,每次“操作”都会返回新对象。


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

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

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


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



  • 2
    点赞
  • 0
    评论
  • 5
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值