BigDecimal解决精度问题

前提

对于需要精确计算得场景和一些需要精确保留小数位的场景,可以使用BigDeciaml来做操作

举个例子,两数相乘或者相除:

        double a = 1.235;
        double b = 100.00;
        System.out.println(a * b);  // 期望结果:123.4

        double c = 123.30;
        double d = 100.00;
        System.out.println(c / d); //期望结果:1.233

实际结果:

123.50000000000001
1.2329999999999999

使用BigDeciaml

        BigDecimal a = new BigDecimal("1.235");
        BigDecimal b = new BigDecimal("100.00");
        BigDecimal c = new BigDecimal("123.30");
        BigDecimal d = new BigDecimal("100.00");

        System.out.println(a.multiply(b));
        System.out.println(c.divide(d));

实际结果:

123.50000
1.233

构建

使用字符串来构造BigDecimal对象,如下

BigDecimal bd = new BigDecimal("0.1");  

错误做法:

下面这种,使用double类型的参数构造BigDecimal,会有精度问题,不要使用

BigDecimal bd = new BigDecimal(0.1);  

结果:

0.1000000000000000055511151231257827021181583404541015625

常用方法

  1. add(BigDecimal)

BigDecimal对象中的值相加,返回BigDecimal对象

  1. subtract(BigDecimal)

BigDecimal对象中的值相减,返回BigDecimal对象

  1. multiply(BigDecimal)

BigDecimal对象中的值相乘,返回BigDecimal对象

  1. divide(BigDecimal)

BigDecimal对象中的值相除,返回BigDecimal对象

  1. toString()

将BigDecimal对象中的值转换成字符串

  1. doubleValue()

将BigDecimal对象中的值转换成双精度数

  1. floatValue()

将BigDecimal对象中的值转换成单精度数

  1. longValue()

将BigDecimal对象中的值转换成长整数

  1. intValue()

将BigDecimal对象中的值转换成整数

  1. compareTo(BigDecimal val);

比较大小:-1小于;0相等;1大于

    System.out.println(new BigDecimal("0.1").compareTo(new BigDecimal("0.2")));
    System.out.println(new BigDecimal("0.2").compareTo(new BigDecimal("0.1")));
    System.out.println(new BigDecimal("0.123").compareTo(new BigDecimal("0.123000000")));

结果:

-1
1
0
  1. BigDecimal setScale(int newScale, int roundingMode)

roundingMode:

public static final int ROUND_HALF_UP = 4; //向上取

public static final int ROUND_HALF_DOWN = 5; //向下取

.......

BigDecimal bigDecimal = new BigDecimal("0.12345678").setScale(2, BigDecimal.ROUND_HALF_UP);
System.out.println(bigDecimal);

结果:

0.12

工具类


public class BigDecimalUtils {

    /**
     * 除法默认保留精度
     */
    private static final int DEF_DIV_SCALE = 10;

    /**
     * 默认舍入模式(ROUND_HALF_UP:四舍五入)
     */
    private static final int DEF_ROUNDING_MODE = BigDecimal.ROUND_HALF_UP;

    private static final String FORMAT_1 = "#.##";

    /**
     * 将字符串转换为 BigDecimal
     *
     * @param value
     * @return
     */
    public static BigDecimal of(String value) {
        return value == null ? null : new BigDecimal(value);
    }

    /**
     * v1 + v2
     *
     * @param v1 被加数
     * @param v2 加数
     * @return 两个参数的和
     */

    public static BigDecimal add(BigDecimal v1, BigDecimal v2) {
        return v1.add(v2);
    }

    /**
     * args[0] + args[1] + ... + args[n]
     *
     * @param args
     * @return
     */
    public static BigDecimal add(BigDecimal... args) {
        if (args == null || args.length <= 1) {
            throw new IllegalArgumentException("args Contains at least two parameters");
        }
        BigDecimal result = args[0];
        for (int i = 1; i < args.length; i++) {
            result = add(result, args[i]);
        }
        return result;
    }


    /**
     * v1 - v2
     *
     * @param v1 被加数
     * @param v2 加数
     * @return 两个参数的和
     */

    public static BigDecimal subtract(BigDecimal v1, BigDecimal v2) {
        return v1.subtract(v2);
    }

    /**
     * args[0] - args[1] - ... - args[n]
     *
     * @param args
     * @return
     */
    public static BigDecimal subtract(BigDecimal... args) {
        if (args == null || args.length <= 1) {
            throw new IllegalArgumentException("args Contains at least two parameters");
        }
        BigDecimal result = args[0];
        for (int i = 1; i < args.length; i++) {
            result = subtract(result, args[i]);
        }
        return result;
    }

    /**
     * v1 * v2
     *
     * @param v1 被乘数
     * @param v2 乘数
     * @return 两个参数的积
     */

    public static BigDecimal multiply(BigDecimal v1, BigDecimal v2) {
        return v1.multiply(v2);
    }

    /**
     * args[0] * args[1] * ... * args[n]
     *
     * @return 两个参数的积
     */

    public static BigDecimal multiply(BigDecimal... args) {
        if (args == null || args.length <= 1) {
            throw new IllegalArgumentException("args Contains at least two parameters");
        }
        BigDecimal result = args[0];
        for (int i = 1; i < args.length; i++) {
            result = multiply(result, args[i]);
        }
        return result;
    }


    /**
     * v1 / v2
     *
     * @param v1 被乘数
     * @param v2 乘数
     * @return 两个参数的积
     */

    public static BigDecimal divide(BigDecimal v1, BigDecimal v2) {
        return v1.divide(v2, DEF_DIV_SCALE, DEF_ROUNDING_MODE);
    }

    /**
     * args[0] / args[1] / ... / args[n]
     *
     * @return 两个参数的积
     */

    public static BigDecimal divide(BigDecimal... args) {
        if (args == null || args.length <= 1) {
            throw new IllegalArgumentException("args Contains at least two parameters");
        }
        BigDecimal result = args[0];
        for (int i = 1; i < args.length; i++) {
            result = divide(result, args[i]);
        }
        return result;
    }

    /**
     * 四舍五入,保留两位小数
     *
     * @param d
     * @return
     */
    public static BigDecimal round(BigDecimal d) {
        if (d == null) {
            return null;
        }
        return d.setScale(2, BigDecimal.ROUND_HALF_UP);
    }


    /**
     * v1>v2?
     *
     * @param v1
     * @param v2
     * @return
     */
    public static boolean gt(BigDecimal v1, BigDecimal v2) {
        return v1.compareTo(v2) > 0;
    }

    /**
     * v1 == v2
     *
     * @param v1
     * @param v2
     * @return
     */
    public static boolean eq(BigDecimal v1, BigDecimal v2) {
        return v1.compareTo(v2) == 0;
    }

    /**
     * 判断 values 是否等于 0?
     *
     * @param value
     * @return
     */
    public static boolean eq0(BigDecimal value) {
        return BigDecimal.ZERO.compareTo(value) == 0;
    }

    /**
     * v1>=v2?
     *
     * @param v1
     * @param v2
     * @return
     */
    public static boolean ge(BigDecimal v1, BigDecimal v2) {
        return v1.compareTo(v2) >= 0;
    }

    /**
     * v1<v2?
     *
     * @param v1
     * @param v2
     * @return
     */
    public static boolean lt(BigDecimal v1, BigDecimal v2) {
        return v1.compareTo(v2) < 0;
    }

    /**
     * 格式化,保留2为小数
     *
     * @param value
     * @return
     */
    public static String format(BigDecimal value) {
        if (value == null) {
            return null;
        }
        DecimalFormat df = new DecimalFormat(FORMAT_1);
        return df.format(value);
    }

    /**
     * 格式化
     *
     * @param value
     * @param pattern 模式字符串,如:#.##
     * @return
     */
    public static String format(BigDecimal value, String pattern) {
        if (value == null) {
            return null;
        }
        DecimalFormat df = new DecimalFormat(pattern);
        return df.format(value);
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值