在做金融类系统处理金额数据时,double提供的精度位数有限,进行大量资产的核查清算时,容易因位数过多产生精度不够的情况。

Java的BigDecimal在这方面支持较好,可以提供任意位的精确计算,不过其效率一般,为了探究与double的性能差距,简单测了一亿次迭代情况下的加减乘除运算,进行比较,本次试验使用我的渣渣办公本,i5-2410m 4G内存。

通过测试,BigDecimal与double的性能差距在100倍这个量级,测试一亿次迭代数据,处理效率尚可在可接受范围。

结果图(单位毫秒):

BigDecimal性能

几点注意/说明:

  • BigDecimal的初始化,使用double进行初始化时,并不是精确值,会有一些不可预测性,建议使用字符串进行初始化。
  • 本次在做测试时未关hotspot,多次迭代自动编译本地代码执行,基本也和实际场景差不多。
  • 多次迭代的测试时,为尽量减小编译过度优化,令每次迭代对实际值本身进行修改,并于迭代后实际使用该值输出。

原始数据:单位毫秒

double add add double minus BigDecimal minus double multiply BigDecimal multiply double divid BigDecimal divid
145 12996 144 12822 384 17053 995 17520
145 11326 143 12685 356 17043 1035 17493
131 11564 144 13530 362 17266 1040 17453
139 11177 151 13148 360 17020 1021 17725
131 11564 144 13530 365 16902 1069 17707
139 11184 133 13687 400 16818 1064 17527
139 11177 151 13148 376 17416 1044 17730
138 11177 140 12876 372 17188 1045 17740

 

平均值和倍数:

double add BigDecimal add double minus BigDecimal minus double multiply BigDecimal multiply double divid BigDecimal divid
138 11521 144 13178 372 17088 1039 17612
倍数 83 倍数 92 倍数 46 倍数 17

 

源代码:

 

package p001;
package p001;
 
import java.math.BigDecimal;
import static util.Print.print;;
public class BigDecimalTester {
 
	public static void main(String[] args) {
		for(int i=1;i<3;i++){
		add(100000000);
		minus(100000000);
		multiply(100000000);
		divid(100000000);
		}
	}
 
	public static void add(int n){
		print("add n="+n);
		long start,end;
		double value_double = 20000.22;
		BigDecimal bd = new BigDecimal("20000.22");
 
		start = System.currentTimeMillis();
		BigDecimal temp_bd=new BigDecimal("0");
		for(int i=1;i<n;i++){
			value_double = value_double + 2323.349;
		}
		end = System.currentTimeMillis();
 
		print(end-start);
		start = System.currentTimeMillis();
		for(int i=1;i<n;i++){
			bd = bd.add(new BigDecimal("2323.349"));
		}
		end = System.currentTimeMillis();
		print(end-start);
 
		print(value_double);
		print(bd);
	}
	public static void minus(int n){
		print("minus n="+n);
		long start,end;
		double value_double = 20000.22;
		BigDecimal bd = new BigDecimal("20000.22");
 
		start = System.currentTimeMillis();
		for(int i=1;i<n;i++){
			value_double = value_double - 2323.349;
		}
		end = System.currentTimeMillis();
		print(end-start);
 
		start = System.currentTimeMillis();
		BigDecimal temp_bd=new BigDecimal("0");
		for(int i=1;i<n;i++){
			bd = bd.subtract(new BigDecimal("2323.349"));
		}
		end = System.currentTimeMillis();
		print(end-start);
 
		print(value_double);
		print(bd);
	}
 
	public static void multiply(int n){
		print("multiply n="+n);
		long start,end;
		double value_double = 20000.22;
		BigDecimal bd = new BigDecimal("20000.22");
 
		double delta_double = value_double * 1.237 - value_double;
		BigDecimal delta_bd = bd.multiply(new BigDecimal("1.237")).subtract(bd);
 
		start = System.currentTimeMillis();
		for(int i=1;i<n;i++){
			value_double = value_double * 1.237;
			value_double = value_double - delta_double;
		}
		end = System.currentTimeMillis();
		print(end-start);
 
		start = System.currentTimeMillis();
		for(int i=1;i<n;i++){
			bd = bd.multiply(new BigDecimal("1.237"));
			bd = bd.subtract(delta_bd).setScale(2, BigDecimal.ROUND_HALF_UP);
		}
 
		end = System.currentTimeMillis();
		print(end-start);
		print(value_double);
		print(bd);
	}
	public static void divid(int n){
		print("divid n="+n);
		long start,end;
		double value_double = 20000.22;
		BigDecimal bd = new BigDecimal("20000.22");
 
		double delta_double = value_double / 0.965 - value_double;
		BigDecimal delta_bd = bd.divide(new BigDecimal("0.965"),2).subtract(bd);
 
		start = System.currentTimeMillis();
		for(int i=1;i<n;i++){
			value_double= value_double / 0.965;
			value_double = value_double - delta_double;
		}
 
		end = System.currentTimeMillis();
		print(end-start);
		start = System.currentTimeMillis();
		for(int i=1;i<n;i++){
			bd  = bd.divide(new BigDecimal("0.965"),2);
			bd = bd.subtract(delta_bd).setScale(2, BigDecimal.ROUND_HALF_UP);
		}
 
		end = System.currentTimeMillis();
		print(end-start);
		print(value_double);
		print(bd);
	}
}
如无特殊声明,本文为Zhonghcc原创文章,转载请注明: 转载自Zhonghcc 's Blog
本文链接地址: BigDecimal与double四则运算性能对比

 回复

(必须)

(必须)

© 2017 Zhonghcc 's Blog Suffusion theme by Sayontan Sinha