问题起因
商品价格为19.9元,微信调起支付价格为19.89
深挖原因如下
微信官方文档规定:
交易金额
交易金额默认为人民币交易,接口中参数支付金额单位为【分】,参数值不能带小数。对账单中的交易金额单位为【元】。
外币交易的支付金额精确到币种的最小单位,参数值不能带小数点。
支付宝没有这种规定,并不会产生这种问题。
问题是double*100丢失精度造成的
问题代码:
double v = Double.valueOf("19.9")* 100;
int fee = Double.valueOf(v).intValue();
猜下这个fee的值会是多少?答案:19.89
是不是很无语。。。
想让Double不丢失精度,要用BigDecimal处理
测试代码如下:
public static void main(String args[]){
double v = Double.valueOf("19.9")* 100;
int fee = Double.valueOf(v).intValue();
System.out.println(fee);
BigDecimal v1 = new BigDecimal("19.9");
BigDecimal v2 = new BigDecimal("100");
Double b = v1.multiply(v2).doubleValue();
int fee1 = b.intValue();
System.out.println(fee1);
}
打印结果:
如上图,BigDecimal类型的乘法可以很好的解决这种精度问题。
BigDecimal精确运算使用总结
加法:
public static double add(double value1,double value2){
BigDecimal b1 = new BigDecimal(Double.valueOf(value1));
BigDecimal b2 = new BigDecimal(Double.valueOf(value2));
return b1.add(b2).doubleValue();
}
减法:
public static double sub(double value1,double value2){
BigDecimal b1 = new BigDecimal(Double.valueOf(value1));
BigDecimal b2 = new BigDecimal(Double.valueOf(value2));
return b1.subtract(b2).doubleValue();
}
乘法:
public static double mul(double value1,double value2){
BigDecimal b1 = new BigDecimal(Double.valueOf(value1));
BigDecimal b2 = new BigDecimal(Double.valueOf(value2));
return b1.multiply(b2).doubleValue();
}
除法:
public static double div(double value1,double value2,int scale) throws IllegalAccessException{
//如果精确范围小于0,抛出异常信息
if(scale<0){
throw new IllegalAccessException("精确度不能小于0");
}
BigDecimal b1 = new BigDecimal(Double.valueOf(value1));
BigDecimal b2 = new BigDecimal(Double.valueOf(value2));
return b1.divide(b2, scale).doubleValue();
}