概述
1、继续使用Double类型
其实只要在计算时使用封装的工具类,继续使用Double类型精度也不会丢失;转换为BigDecimal时,构造函数采用String那一个。
package com.sugarppig.general.utils;
import com.sugarppig.common.exception.GeneralException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
/**
* @author SugarPPig
* @date 2020-12-09 16:05
* @decription Double 精确计算工具
*/
public class DoubleArithUtil {
/**
* 提供精确加法计算的add方法
*
* @param value1
* 被加数
* @param value2
* 加数
* @return 两个参数的和
*/
public static double add(double value1, double value2) {
BigDecimal b1 = new BigDecimal(String.valueOf(value1));
BigDecimal b2 = new BigDecimal(String.valueOf(value2));
return b1.add(b2).doubleValue();
}
/**
* 提供精确减法运算的sub方法
*
* @param value1
* 被减数
* @param value2
* 减数
* @return 两个参数的差
*/
public static double sub(double value1, double value2) {
BigDecimal b1 = new BigDecimal(String.valueOf(value1));
BigDecimal b2 = new BigDecimal(String.valueOf(value2));
return b1.subtract(b2).doubleValue();
}
/**
* 提供精确乘法运算的mul方法
*
* @param value1
* 被乘数
* @param value2
* 乘数
* @return 两个参数的积
*/
public static Double mul(Double value1, Double value2) {
if (value1 == null || value2 == null) {
return 0d;
}
BigDecimal b1 = new BigDecimal(String.valueOf(value1));
BigDecimal b2 = new BigDecimal(String.valueOf(value2));
return b1.multiply(b2).doubleValue();
}
/**
* 提供精确的除法运算方法div
*
* @param value1
* 被除数
* @param value2
* 除数
* @param scale
* 精确范围
* @return 两个参数的商,默认四舍五入
* @throws GeneralException
*/
public static Double div(double value1, double value2, int scale) {
// 如果精确范围小于0,抛出异常信息
if (scale < 0) {
throw new GeneralException("精确度不能小于0");
}
if (value2 == 0) {
return 0d;
}
BigDecimal b1 = new BigDecimal(String.valueOf(value1));
BigDecimal b2 = new BigDecimal(String.valueOf(value2));
return b1.divide(b2, scale, RoundingMode.HALF_UP).doubleValue();
}
/**
* 计算多个值的乘积
*/
public static Double muls(Double... args) {
if (args.length < 2) {
throw new GeneralException("参数至少为2个");
}
List<Double> doubles = Arrays.asList(args);
if (doubles.stream().anyMatch(Objects::isNull)) {
return 0d;
}
return doubles.parallelStream().reduce(1d, DoubleArithUtil::mul);
}
/**
* 计算多个值的和
*/
public static Double adds(Double... args) {
if (args.length < 2) {
throw new GeneralException("参数至少为2个");
}
List<Double> doubles = Arrays.asList(args);
if (doubles.stream().anyMatch(Objects::isNull)) {
return 0d;
}
return doubles.parallelStream().reduce(0d, DoubleArithUtil::add);
}
/**
* 计算多个值的和,元素为null时记为0d参与运算
*/
public static Double addsNull(Double... args) {
if (args.length < 2) {
throw new GeneralException("参数至少为2个");
}
List<Double> doubles = Arrays.asList(args);
return doubles.parallelStream().map(e -> e == null ? 0d : e).reduce(0d, DoubleArithUtil::add);
}
}
2、将Double类型改为BigDecimal类型
BigDecimal工具类,将Double的工具类稍微改动了下。
package com.sugarppig.general.utils;
import com.sugarppig.common.exception.GeneralException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
/**
* @author SugarPPig
* @date 2020-12-10 10:03
* @decription BigDecimal 精确计算工具
*/
public class BigDecimalArithUtil {
/**
* 提供精确加法计算的add方法
*
* @param value1
* 被加数
* @param value2
* 加数
* @return 两个参数的和
*/
public static BigDecimal add(BigDecimal value1, BigDecimal value2) {
return value1.add(value2);
}
/**
* 提供精确减法运算的sub方法
*
* @param value1
* 被减数
* @param value2
* 减数
* @return 两个参数的差
*/
public static BigDecimal sub(BigDecimal value1, BigDecimal value2) {
return value1.subtract(value2);
}
/**
* 提供精确乘法运算的mul方法
*
* @param value1
* 被乘数
* @param value2
* 乘数
* @return 两个参数的积
*/
public static BigDecimal mul(BigDecimal value1, BigDecimal value2) {
if (value1 == null || value2 == null) {
return BigDecimal.ZERO;
}
return value1.multiply(value2);
}
/**
* 提供精确的除法运算方法div
*
* @param value1
* 被除数
* @param value2
* 除数
* @param scale
* 精确范围
* @return 两个参数的商,默认四舍五入
* @throws GeneralException
*/
public static BigDecimal div(BigDecimal value1, BigDecimal value2, int scale) {
// 如果精确范围小于0,抛出异常信息
if (scale < 0) {
throw new GeneralException("精确度不能小于0");
}
if (value2.compareTo(BigDecimal.ZERO) == 0) {
return BigDecimal.ZERO;
}
return value1.divide(value2, scale, RoundingMode.HALF_UP);
}
/**
* 计算多个值的乘积
*/
public static BigDecimal muls(BigDecimal... args) {
if (args.length < 2) {
throw new GeneralException("参数至少为2个");
}
List<BigDecimal> bigDecimals = Arrays.asList(args);
if (bigDecimals.stream().anyMatch(Objects::isNull)) {
return BigDecimal.ZERO;
}
return bigDecimals.parallelStream().reduce(BigDecimal.ONE, ArithUtil::mul);
}
/**
* 计算多个值的和
*/
public static BigDecimal adds(BigDecimal... args) {
if (args.length < 2) {
throw new GeneralException("参数至少为2个");
}
List<BigDecimal> BigDecimals = Arrays.asList(args);
if (BigDecimals.stream().anyMatch(Objects::isNull)) {
return BigDecimal.ZERO;
}
return BigDecimals.parallelStream().reduce(BigDecimal.ZERO, ArithUtil::add);
}
/**
* 计算多个值的和,元素为null时记为0参与运算
*/
public static BigDecimal addsNull(BigDecimal... args) {
if (args.length < 2) {
throw new GeneralException("参数至少为2个");
}
List<BigDecimal> BigDecimals = Arrays.asList(args);
return BigDecimals.parallelStream().map(e -> e == null ? BigDecimal.ZERO : e).reduce(BigDecimal.ZERO,
ArithUtil::add);
}
}
注意!!!使用BigDecimal比较两个数,值的大小时,一定要使用compareTo,不要用equals,源码显示它会检查小数位数是否相等。
测试两种比较方式的区别
最后
以上就是现实饼干为你收集整理的Double类型丢失精度的两种解决方案的全部内容,希望文章能够帮你解决Double类型丢失精度的两种解决方案所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复