项目中遇到了数值运算,如网上所写的,一般有这几个方法:

 

/**
	* 提供精确的加法运算。
	* @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();
	}
/**
	* 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指
	* 定精度,以后的数字四舍五入。
	* @param v1 被除数
	* @param v2 除数
	* @param scale 表示需要精确到小数点以后几位。
	* @return 两个参数的商
	*/
	public static double div(double v1, double v2, int scale) {
	   if (scale < 0) {
	    System.err.println("除法精度必须大于0!");
	    return 0;
	   }
	   BigDecimal b1 = new BigDecimal(Double.toString(v1));
	   BigDecimal b2 = new BigDecimal(Double.toString(v2));
	   return (b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP)).doubleValue();
	}	

 

但是这里,我还有两个地方需要做一些变化:

1、乘法运算需要做精度的四舍五入

2、double会自动进行科学计数法

 

对于第一点新增mul方法

public static double mul(double v1, double v2,int scale) {
		   BigDecimal b1 = new BigDecimal(Double.toString(v1));
		   BigDecimal b2 = new BigDecimal(Double.toString(v2));
		   return (b1.multiply(b2).setScale(scale, RoundingMode.HALF_UP)).doubleValue();
		}

这样就可以对所做的运算进行需要的精度的四舍五入

第二点新增double2Str方法

private static String double2Str(double number)
	{
		return DecimalFormat.getInstance().format(number).replace(",","");	
	}

不需要进行格式化,因为项目中把科学计数法的数字传给客户端.Net接收,无法正确转换成数值(除非客户端特殊处理这个科学计数法数值)

当时,对第一点做了一个错误的精度处理:MathContext

public static double mul(double v1, double v2,int scale) {
		   BigDecimal b1 = new BigDecimal(Double.toString(v1));
		   BigDecimal b2 = new BigDecimal(Double.toString(v2));
		   

return b1.multiply(b2, new MathContext(scale,RoundingMode.HALF_UP)).doubleValue();

		   
		}

这个MathContext是从左边第一个数开始算起,而不是从小数点后开始算

 

补充一下舍入RoundingMode

在RoundingMode中HALF_DOWN 没有按照我预期的对数值进行向下取数值有点疑惑

 

double d3 = 102207767.555;
d3=new BigDecimal(d3).setScale(2,RoundingMode.HALF_DOWN).doubleValue();

打印后d3显示102207767.56 不应该是102207767.55?

 

ROUND_CEILING
Rounding mode to round towards positive infinity.
向正无穷方向舍入
ROUND_DOWN
Rounding mode to round towards zero.
向零方向舍入
ROUND_FLOOR
Rounding mode to round towards negative infinity.
向负无穷方向舍入

ROUND_HALF_DOWN

Rounding mode to round towards "nearest neighbor" unless both neighbors are equidistant, in which case round down.
向(距离)最近的一边舍入,除非两边(的距离)是相等,如果是这样,向下舍入, 例如1.55 保留一位小数结果为1.5
ROUND_HALF_EVEN
Rounding mode to round towards the "nearest neighbor" unless both neighbors are equidistant, in which case, round towards the even neighbor.
向(距离)最近的一边舍入,除非两边(的距离)是相等,如果是这样,如果保留位数是奇数,使用ROUND_HALF_UP ,如果是偶数,使用ROUND_HALF_DOWN
ROUND_HALF_UP
Rounding mode to round towards "nearest neighbor" unless both neighbors are equidistant, in which case round up.
向(距离)最近的一边舍入,除非两边(的距离)是相等,如果是这样,向上舍入, 1.55保留一位小数结果为1.6

ROUND_UNNECESSARY

Rounding mode to assert that the requested operation has an exact result, hence no rounding is necessary.
计算结果是精确的,不需要舍入模式
ROUND_UP
Rounding mode to round away from zero.
向远离0的方向舍入

posted on 2014-01-04 17:02  victor321  阅读(501)  评论(0编辑  收藏  举报