版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u012246458/article/details/87864202
需求:
Double和float类型,进行加减乘除操作以后,得到的结果小数点后会有好多位。
例如:0.06-0.01 = 0.049999999999999996
所以在涉及到金额或者利率换算时候,必须使用BigDecimal类型进行计算。
BigDecimal:
在这种情况下我们就需要用到java.math包下面的BigDecimal类,BigDecimal主要用于高精度的数据计算,例如计算金额的时候,还有工程测量计算的时候。BigDecimal的提供了add(),subtract(),multiply()和divide()四种方法,分别为加减乘除,一般计算包含小数的用法为
BigDecimal b1 = new BigDecimal(a1);
BigDecimal b2 = new BigDecimal(a2);
System.out.println(b1.subtract(b2).doubleValue());
其中a1和a2的类型可以为String,Double,int,long等等,我在实际用的时候发现了一个问题,当a1和a2的类型为Double的时候,得到的结果仍然丢失了精度,例如:
BigDecimal b1 = new BigDecimal(0.06);
BigDecimal b2 = new BigDecimal(0.01);
System.out.println(b1.subtract(b2).doubleValue());
得到的结果仍然为0.049999999999999996
可是如果参数类型为String,结果就是正确的,就像这样:
BigDecimal b1 = new BigDecimal("0.06");
BigDecimal b2 = new BigDecimal("0.01");
System.out.println(b1.subtract(b2).doubleValue());
得到的结果为0.05。
经过测试发现,原来在new BigDecimal(0.06)的时候,得到b1的结果为0.059999999999999997779553950749686919152736663818359375,而b2的值为0.01000000000000000020816681711721685132943093776702880859375,这时候就已经精度丢失了,最后得到的结果很显然也会丢失精度,而使用new BigDecimal("0.06")得到的b1仍然为0.06。
所以如果大家要对小数进行精确计算的话,new BigDecimal()的参数一定要用String类型的。
工具类:
package com.baofu.yunfutong.util;
import java.math.BigDecimal;
/**
* Android 精确算法
* 适用于金额、利率换算
*/
public class BigDecimalUtils {
/**
* 提供精确的加法运算
*
* @param v1 被加数
* @param v2 加数
* @param scale 保留scale 位小数
* @return 两个参数的和
*/
public static String add(String v1, String v2, int scale) {
if (scale < 0) {
throw new IllegalArgumentException("保留的小数位数必须大于零");
}
BigDecimal b1 = new BigDecimal(v1);
BigDecimal b2 = new BigDecimal(v2);
return b1.add(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();
}
/**
* 提供精确的减法运算
*
* @param v1 被减数
* @param v2 减数
* @param scale 保留scale 位小数
* @return 两个参数的差
*/
public static String sub(String v1, String v2, int scale) {
if (scale < 0) {
throw new IllegalArgumentException("保留的小数位数必须大于零");
}
BigDecimal b1 = new BigDecimal(v1);
BigDecimal b2 = new BigDecimal(v2);
return b1.subtract(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();
}
/**
* 提供精确的乘法运算
*
* @param v1 被乘数
* @param v2 乘数
* @param scale 保留scale 位小数
* @return 两个参数的积
*/
public static String mul(String v1, String v2, int scale) {
if (scale < 0) {
throw new IllegalArgumentException("保留的小数位数必须大于零");
}
BigDecimal b1 = new BigDecimal(v1);
BigDecimal b2 = new BigDecimal(v2);
return b1.multiply(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();
}
/**
* 提供精确的除法运算。当发生除不尽的情况时,由scale参数指定精度,以后的数字四舍五入
*
* @param v1 被除数
* @param v2 除数
* @param scale 表示需要精确到小数点以后几位
* @return 两个参数的商
*/
public static String div(String v1, String v2, int scale) {
if (scale < 0) {
throw new IllegalArgumentException("保留的小数位数必须大于零");
}
BigDecimal b1 = new BigDecimal(v1);
BigDecimal b2 = new BigDecimal(v2);
return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).toString();
}
/**
* 提供精确的小数位四舍五入处理
*
* @param v 需要四舍五入的数字
* @param scale 小数点后保留几位
* @return 四舍五入后的结果
*/
public static double round(double v, int scale) {
if (scale < 0) {
throw new IllegalArgumentException("保留的小数位数必须大于零");
}
BigDecimal b = new BigDecimal(Double.toString(v));
return b.setScale(scale, BigDecimal.ROUND_HALF_UP).doubleValue();
}
/**
* 提供精确的小数位四舍五入处理
*
* @param v 需要四舍五入的数字
* @param scale 小数点后保留几位
* @return 四舍五入后的结果
*/
public static String round(String v, int scale) {
if (scale < 0) {
throw new IllegalArgumentException("保留的小数位数必须大于零");
}
BigDecimal b = new BigDecimal(v);
return b.setScale(scale, BigDecimal.ROUND_HALF_UP).toString();
}
/**
* 取余数
*
* @param v1 被除数
* @param v2 除数
* @param scale 小数点后保留几位
* @return 余数
*/
public static String remainder(String v1, String v2, int scale) {
if (scale < 0) {
throw new IllegalArgumentException("保留的小数位数必须大于零");
}
BigDecimal b1 = new BigDecimal(v1);
BigDecimal b2 = new BigDecimal(v2);
return b1.remainder(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();
}
/**
* 比较大小
*
* @param v1 被比较数
* @param v2 比较数
* @return 如果v1 大于v2 则 返回true 否则false
*/
public static boolean compare(String v1, String v2) {
BigDecimal b1 = new BigDecimal(v1);
BigDecimal b2 = new BigDecimal(v2);
int bj = b1.compareTo(b2);
if (bj > 0)
return true;
else
return false;
}
}