我是靠谱客的博主 现实饼干,最近开发中收集的这篇文章主要介绍Double类型丢失精度的两种解决方案,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

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类型丢失精度的两种解决方案所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(56)

评论列表共有 0 条评论

立即
投稿
返回
顶部