当前位置: 首页 > article >正文

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);
    }

}

http://www.kler.cn/a/456910.html

相关文章:

  • Excel文件恢复教程:快速找回丢失数据!
  • 【大模型实战篇】Mac本地部署RAGFlow的踩坑史
  • 洪水灾害多智能体分布式模拟示例代码
  • 使用MFC编写一个paddleclas预测软件
  • 使用C++实现一个高效的线程池
  • 使用套接字创建一个服务端,创建一个客户端然后相互通讯
  • 【git】将项目上传到github、gitee
  • 【蓝桥杯每日一题】与或异或——DFS
  • 【Docker命令】如何使用 `docker cp` 命令拷贝容器文件到宿主机
  • Dify智能体进阶:Selenium截取动图
  • Git完整使用经历
  • 0基础带你python入门:pyQT + OpenCV相关练习
  • 调试文件系统(DebugFS )
  • Flutter 实现全局悬浮按钮学习
  • 微信小程序页面传参长度问题
  • Blender真实灰尘粒子动画资产预设 Dust Particles Pro V1.2
  • JVM常用参数
  • 《易经》在 Java 编程中的应用
  • Flutter 异步编程简述
  • 卷积神经网络(CNN)模型 CIFAR-10 数据集 例子
  • 学习,指针和FLASH
  • 02-18.python入门基础一基础算法
  • [江科大STM32] 第五集STM32工程模板——笔记
  • rk356x 下 qt 程序 hdmi不显示鼠标图标
  • 数值分析雨课堂章节测试
  • Java重要面试名词整理(十一):网络编程