Java之BigDecimal的使用及说明

 更新时间:2026年04月09日 14:39:43   作者:Tech_Jia_Hui  
文章简要介绍了BigDecimal在Java中的应用,特别适用于高精度计算场景,详细讲述了double和float的精度问题,强调了BigDecimal的不可变性和线程安全性,还列举了常用方法,包括构造方法、算术运算方法和设置精度的方法,同时指出了使用过程中可能遇到的问题及解决方案

一、BigDecimal概述

BigDecimal 是 Java 中用于高精度计算的类,属于 java.math 包。

它主要用于处理需要极高精度的数值运算。

记住:

在金融计算、价格计算等需要精确小数运算的场景中,BigDecimal 是唯一正确的选择。

二、double、float 类型的坑

double result = 0.1 + 0.2; // 结果为 0.30000000000000004
float a = 1;
float b = 0.9f;
System.out.println(a - b); // 结果为 0.100000024

三、BigDecimal优越性

  • 高精度数值计算:BigDecimal是 Java 中用于高精度数值计算的类。它主要用于处理需要精确表示的十进制数,特别是在金融、货币计算等对精度要求极高的领域。双精度浮点型变量double 虽然可以处理16位有效数,但在实际应用中,可能需要对更大或者更小的数进行运算和处理,BigDecimal 就可以用来对超过16位有效位的数进行精确的运算。一般情况下,对于那些不需要准确计算精度的数字,我们可以直接使用Float和Double处理,但是Double.valueOf(String) 和Float.valueOf(String)会丢失精度。所以开发中,如果我们需要精确计算的结果,则必须使用BigDecimal类来操作。
  • 不可变对象:BigDecimal对象是不可变的,这意味着一旦创建,其数值就不能被修改(即线程安全)。对BigDecimal对象进行的任何操作(如加法、减法、乘法、除法等)都会返回一个新的BigDecimal对象,而原对象保持不变。这种不可变性有助于确保数据的一致性和线程安全性。

当程序中涉及到金额时,必须使用 BigDecimal 而不是 double 或 float 。

double result = 0.1 + 0.2; // 结果为 0.30000000000000004
BigDecimal bd1 = new BigDecimal("0.1");
BigDecimal bd2 = new BigDecimal("0.2");
BigDecimal sum = bd1.add(bd2); // 结果为 0.3

四、BigDecimal 的常用方法

4.1 构造方法

  • new BigDecimal(int val):创建一个具有参数所指定整数值的对象。
  • new BigDecimal(double val):(不推荐使用,因为存在精度丢失问题)创建一个具有参数所指定双精度值的对象。
  • new BigDecimal(long val):创建一个具有参数所指定长整数值的对象
  • new BigDecimal(String val):(推荐使用)创建一个具有参数所指定以字符串表示的数值的对象。
BigDecimal b_int = new BigDecimal(10);
BigDecimal b_double = new BigDecimal(0.1);
BigDecimal b_float = new BigDecimal(0.1f);
BigDecimal b_string = new BigDecimal("0.1");
BigDecimal b_valueof = BigDecimal.valueOf(0.1);
System.out.println("b_int:" + b_int); // b_int:10
System.out.println("b_double:" + b_double); // b_double:0.1000000000000000055511151231257827021181583404541015625
System.out.println("b_float:" + b_float); // b_float:0.100000001490116119384765625
System.out.println("b_string:" + b_string); // b_string:0.1
System.out.println("b_valueof:" + b_valueof); // b_valueof:0.1

使用构造函数时,推荐用 int 或 String 做参数,如果不满足,则建议使用 BigDecimal.valueOf 方法,该方法可接受 int、long、double、float 做参数,但注意不接受 String。

4.2 算术运算方法

  • BigDecimal add(BigDecimal augend) 加法运算。
BigDecimal a = new BigDecimal("10.50");
BigDecimal b = new BigDecimal("3.20");
BigDecimal sum = a.add(b); // 13.70
  • BigDecimal subtract(BigDecimal subtrahend) 减法运算
BigDecimal a = new BigDecimal("10.50");
BigDecimal b = new BigDecimal("3.20");
BigDecimal difference = a.subtract(b); // 7.30
  • BigDecimal multiply(BigDecimal multiplicand) 乘法运算
BigDecimal a = new BigDecimal("10.50");
BigDecimal b = new BigDecimal("3.20");
BigDecimal product = a.multiply(b); // 33.600
  • BigDecimal divide(BigDecimal divisor, int scale, RoundingMode roundingMode) 除法运算
BigDecimal a = new BigDecimal("10.50");
BigDecimal b = new BigDecimal("3.20");

// 四舍五入保留2位小数
BigDecimal quotient1 = a.divide(b, 2, RoundingMode.HALF_UP); // 3.28

// 使用默认舍入模式
BigDecimal quotient2 = a.divide(b, RoundingMode.HALF_UP);
  • BigDecimal remainder(BigDecimal divisor) 取余运算
BigDecimal a = new BigDecimal("10.5");
BigDecimal b = new BigDecimal("3.2");
BigDecimal remainder = a.remainder(b); // 0.9
  • BigDecimal[] divideAndRemainder(BigDecimal divisor) 除法取余
BigDecimal a = new BigDecimal("10.5");
BigDecimal b = new BigDecimal("3.2");
BigDecimal[] results = a.divideAndRemainder(b);
// results[0] = 3 (商)
// results[1] = 0.9 (余数)
  • BigDecimal abs() 绝对值
BigDecimal a = new BigDecimal("-10.50");
BigDecimal absolute = a.abs(); // 10.50
  • BigDecimal pow(int n) 幂运算
BigDecimal a = new BigDecimal("2.5");
BigDecimal power = a.pow(3); // 15.625
  • BigDecimal setScale(int newScale, RoundingMode roundingMode) 四舍五入
BigDecimal a = new BigDecimal("3.1415926");

// 四舍五入保留3位小数
BigDecimal rounded = a.setScale(3, RoundingMode.HALF_UP); // 3.142

// 直接截断
BigDecimal truncated = a.setScale(3, RoundingMode.DOWN); // 3.141
  • int compareTo(BigDecimal val) 比较运算
BigDecimal a = new BigDecimal("10.50");
BigDecimal b = new BigDecimal("10.5");

int result = a.compareTo(b);
// result = 0 (相等)
// result < 0 (a < b)
// result > 0 (a > b)

五、BigDecimal遇到的问题

5.1 相除精度丢失的问题

问题:两数相除,如果9/3=3整除没问题,但是10/3=0.33333333…除不尽,这里不能让电脑一直除不尽,所以BigDecimal做出一些限制;

必须按照(数,保留小数位(最好要合理限制最大精度),舍入方式)来操作,否则就会抛出异常,例如:

public static void main(String[] args) {
    BigDecimal a = new BigDecimal(10);
    BigDecimal b = new BigDecimal(3);
    BigDecimal c = a.divide(b);
}

执行:抛出

Exception in thread “main” java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
at java.math.BigDecimal.divide(BigDecimal.java:1616)

5.2 BigDecimal初始化时入参使用String类型

如果不是数字会抛异常NumberFormatException

// java.lang.NumberFormatException
BigDecimal val = new BigDecimal("a");
System.out.println(val);

5.3 用 equals 判断相等

BigDecimal x = new BigDecimal("1.0");
BigDecimal y = new BigDecimal("1.00");
System.out.println(x.equals(y));  //false   尽管 1.0 和 1.00 的数值相等,但精度不一样,equals 判定为不同。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • java实现word转pdf or直接生成pdf文件

    java实现word转pdf or直接生成pdf文件

    这篇文章主要介绍了java实现word转pdf or直接生成pdf文件方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-04-04
  • MyBatis中如何优雅的使用枚举详解

    MyBatis中如何优雅的使用枚举详解

    枚举类型是我们在开发中经常遇到的一个类型,最近在学习MyBatis,但是发现网上没有详细介绍MyBatis如何使用枚举的相关文章,索性就自己写一篇,下面这篇文章主要给大家介绍了关于在MyBatis中如何优雅的使用枚举的相关资料,需要的朋友可以参考借鉴。
    2017-08-08
  • Mybatis使用concat函数问题

    Mybatis使用concat函数问题

    这篇文章主要介绍了Mybatis使用concat函数问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-02-02
  • java数组排序示例(冒泡排序、快速排序、希尔排序、选择排序)

    java数组排序示例(冒泡排序、快速排序、希尔排序、选择排序)

    java中在运用数组进行排序功能时,一般有四种方法:快速排序法、冒泡法、选择排序法、插入排序法(希尔排序(Shell Sort)是插入排序的一种),下面是一些示例,需要的朋友可以参考下
    2014-03-03
  • Redis Java Lettuce驱动框架原理解析

    Redis Java Lettuce驱动框架原理解析

    这篇文章主要介绍了Redis Java Lettuce驱动框架原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-12-12
  • 详解java 三种调用机制(同步、回调、异步)

    详解java 三种调用机制(同步、回调、异步)

    这篇文章主要介绍了java 三种调用机制(同步、回调、异步),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-04-04
  • java中常用注解@TableId的详细解析

    java中常用注解@TableId的详细解析

    @TableId注解是一种常见的Java注解,通常在使用关系型数据库进行对象关系映射(ORM)时使用,这篇文章主要介绍了java中常用注解@TableId的详细解析,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2025-06-06
  • Java数据库连接PreparedStatement的使用详解

    Java数据库连接PreparedStatement的使用详解

    这篇文章主要介绍了Java数据库连接PreparedStatement的使用详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-08-08
  • java秒杀之redis限流操作详解

    java秒杀之redis限流操作详解

    这篇文章主要为大家详细介绍了java秒杀之redis限流操作,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-11-11
  • @ConfigurationProperties绑定配置信息至Array、List、Map、Bean的实现

    @ConfigurationProperties绑定配置信息至Array、List、Map、Bean的实现

    这篇文章主要介绍了@ConfigurationProperties绑定配置信息至Array、List、Map、Bean的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-05-05

最新评论