java中的数据精度计算问题

网上看了一些资料,在开发中遇到金额的计算很实用啊!!做报表,统计等,会出现精度误差,导致得不到我们要的结果,例如

System.out.println(0.05 + 0.01); 
System.out.println(1.0 - 0.42); 
System.out.println(4.015 * 100); 
System.out.println(123.3 / 100);
//你的期望输出是什么?可实际的输出确实这样的: 
0.060000000000000005 
0.5800000000000001 
401.49999999999994 
1.2329999999999999 


这个问题就非常严重了,如果你有128.3元要购买商品,而计算机却认为你只有128.29999999999999元,钱不够,计算机拒绝交易。

这时候就会想到四舍五入,但是在实际商业项目中就会出现一些错误。

public double round(double value){ 
return Math.round( value * 100 ) / 100.0; 
} 
以上代码输出也会有误差所以.......

如果需要精确计算,非要用String来够造BigDecimal不可!

/** 
* 提供精确的加法运算。 
* @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(); 
}
 <pre name="code" class="java">/** 
* 提供精确的加法运算 
* @param v1 
* @param v2 
* @return 两个参数数学加和,以字符串格式返回 
*/ 
public static String add(String v1, String v2) { 
 BigDecimal b1 = new BigDecimal(v1);
 BigDecimal b2 = new BigDecimal(v2); 
 return b1.add(b2).toString(); 
} 
/**
* 提供精确的减法运算。
* @param v1
* @param v2
* @return 两个参数的差
*/
public static double subtract(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 String subtract(String v1, String v2) {
BigDecimal b1 = new BigDecimal(v1);
BigDecimal b2 = new BigDecimal(v2);
return b1.subtract(b2).toString();
}
/**
* 提供精确的乘法运算。
* @param v1
* @param v2
* @return 两个参数的积 */
public static double multiply(double v1, double v2) {
BigDecimal b1 = new BigDecimal(Double.toString(v1));
  BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.multiply(b2).doubleValue();
 }

/**
* 提供精确的乘法运算
* @param v1
* @param v2
* @return 两个参数的数学积,以字符串格式返回
*/
public static String multiply(String v1, String v2) {
BigDecimal b1 = new BigDecimal(v1);
  BigDecimal b2 = new BigDecimal(v2);
return b1.multiply(b2).toString();
}
/**
* 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到
* 小数点以后10位,以后的数字四舍五入,舍入模式采用ROUND_HALF_EVEN
* @param v1
 * @param v2
* @return 两个参数的商
*/
public static double divide(double v1, double v2) {
return divide(v1, v2, DEFAULT_DIV_SCALE); }
/**
* 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指
* 定精度,以后的数字四舍五入。舍入模式采用ROUND_HALF_EVEN
* @param v1
* @param v2
* @param scale 表示需要精确到小数点以后几位。
* @return 两个参数的商
*/
public static double divide(double v1,double v2, int scale) {
return divide(v1, v2, scale, BigDecimal.ROUND_HALF_EVEN); }

/**
* 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指
* 定精度,以后的数字四舍五入。舍入模式采用用户指定舍入模式
* @param v1
* @param v2
* @param scale 表示需要精确到小数点以后几位
* @param round_mode 表示用户指定的舍入模式
* @return 两个参数的商
*/
public static double divide(double v1,double v2,int scale, int round_mode){
if(scale < 0)
{
throw new IllegalArgumentException("The scale must be a positive integer or zero");
 }
BigDecimal b1 = new BigDecimal(Double.toString(v1));
  BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.divide(b2, scale, round_mode).doubleValue();
}
/**
* 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到
* 小数点以后10位,以后的数字四舍五入,舍入模式采用ROUND_HALF_EVEN
* @param v1
* @param v2
* @return 两个参数的商,以字符串格式返回
*/
public static String divide(String v1, String v2) {
return divide(v1, v2, DEFAULT_DIV_SCALE);
}

**
* 提供精确的小数位四舍五入处理,舍入模式采用ROUND_HALF_EVEN
* @param v 需要四舍五入的数字
* @param scale 小数点后保留几位
* @return 四舍五入后的结果 */
public static double round(double v,int scale)
{
return round(v, scale, BigDecimal.ROUND_HALF_EVEN);
}

/**
* 提供精确的小数位四舍五入处理
* @param v 需要四舍五入的数字
* @param scale 小数点后保留几位
* @param round_mode 指定的舍入模式
* @return 四舍五入后的结果,以字符串格式返回
*/
public static String round(String v, int scale, int round_mode) {
if(scale<0) {
throw new IllegalArgumentException("The scale must be a positive integer or zero");
 }
BigDecimal b = new BigDecimal(v);
return b.setScale(scale, round_mode).toString();
}


 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值