BigDecimal在项目中怎么用?

为什么用BigDecimal?

在编程的世界里,BigDecimal 是一位精确而谨慎的数学家,它的存在解决了一个棘手的问题:浮点数(如 floatdouble)在某些情况下的不精确表达。

尤其是在财务计算中,精确度是至关重要的。作为一名程序员,如果负责计算巨额交易的利息。即使是极小的误差,也可能导致巨大的经济损失。在这种情况下,如果使用 floatdouble 来表示货币,那很有可能你会因为精度丢失的问题导致你的年终奖被扣走

这时就需要使用BigDecimal这个能够精确地测量和表示的API去处理这些数字。可以精确地控制数值的小数点后位数,避免了浮点数的舍入误差。

注意:正因为它的精度高,所以计算的时候,会比正常的计算慢数十倍。所以根据自己业务需要去做选择

基本使用

那么对上面我们的业务做好权衡之后,我们就要去使用它了。

1. 构造

简单来说BigDecimal就是java中的一个类,所以我们在使用的时候就将它按照一个对象去处理

  • 通过字符串构造new BigDecimal(String val)。使用字符串构造 BigDecimal 是推荐的方法,因为它可以避免由于浮点数不精确表示而导致的意外结果。
  • 通过双精度类型构造new BigDecimal(double val)。这种方式虽然也可以使用,但不推荐,因为它可能会引起浮点数本身的精度问题。

我们在创建了一个对象之后它就是不可变的了,如果我们想要在一个循环里面去相加就需要去创建一个0

这里推荐一个创建0的方法,这种方式也是性能最高的
BigDecimal zero = BigDecimal.ZERO;

剩下的我们只能通过的基本运算去做一下相关的修改

2. 基本运算

  • 加法add(BigDecimal augend)
  • 减法subtract(BigDecimal subtrahend)
  • 乘法multiply(BigDecimal multiplicand)
  • 除法divide(BigDecimal divisor, int scale, RoundingMode roundingMode)

需要特别注意 divide 方法,因为在做除法的时候可能会产生无限循环小数,需要指定小数点后的位数(scale)和舍入模式。

3. 精确度和舍入模式

因为除法的特殊性,所以我在这里单独拉出来讲一讲
BigDecimal有两种模式即标题的两种模式,对应divide后面的两个参数

  • 精确度(Scale) 精确度是指小数点后保留的位数。在进行除法时,如果结果是一个无限循环小数,没有适当的精确度设置,将会抛出 ArithmeticException 异常。
  • 舍入模式(RoundingMode) 它其实就是 Java 中的 RoundingMode 是一个枚举类型,它定义了几种不同的舍入行为。以下是一些常用的舍入模式:
  • RoundingMode.UP:远离零方向舍入。
  • RoundingMode.DOWN:靠近零方向舍入。
  • RoundingMode.CEILING:向正无穷方向舍入。
  • RoundingMode.FLOOR:向负无穷方向舍入。
  • RoundingMode.HALF_UP:四舍五入(若舍弃部分≥0.5,则舍入行为与 RoundingMode.UP 相同)

一般常用的就是上面的这几种

示例代码:

java 复制代码
import java.math.BigDecimal;
import java.math.RoundingMode;

public class BigDecimalDemo {
    public static void main(String[] args) {
        BigDecimal dividend = new BigDecimal("10");
        BigDecimal divisor = new BigDecimal("3");

        // 使用不同的舍入模式
        BigDecimal resultHalfUp = dividend.divide(divisor, 2, RoundingMode.HALF_UP);
        BigDecimal resultDown = dividend.divide(divisor, 2, RoundingMode.DOWN);

        System.out.println("Result with HALF_UP: " + resultHalfUp); // 输出 "Result with HALF_UP: 3.33"
        System.out.println("Result with DOWN: " + resultDown);      // 输出 "Result with DOWN: 3.33"
    }
}

4. 如何比较

我们在对BigDecimal 类的比较操作需要特别的注意,因为它与基本数据类型或其他对象类型的比较有所不同。主要原因是 BigDecimal 包含了数值和精确度(Scale)两个部分,这两部分都会影响比较的结果。


为什么会出现这样的情况?

主要是因为它们的精确度不同,直接使用 equals 方法比较时会返回 false。这是因为 equals 方法考虑了对象的数值和精确度。

所以我们就需要使用 compareTo 进行数值比较 示例:

java 复制代码
BigDecimal a = new BigDecimal("2.00");
BigDecimal b = new BigDecimal("2.0");

boolean isEqual = a.equals(b);        // 返回 false,因为精确度不同
int comparison = a.compareTo(b);      // 返回 0,数值相等

实战使用

  • 那么我在开发的过程中就遇到了在对接银联支付的时候,银联需要将金钱转化为Integer类型给传到json里面在发送过去,那么下面是我的代码处理。
java 复制代码
int amount = order.getPayPrice().multiply(BigDecimal.TEN).multiply(BigDecimal.TEN).intValue();
  • 在计算税率的时候的一个实战代码
java 复制代码
import java.math.BigDecimal;
import java.math.RoundingMode;

public class FinancialCalculationExample {
    public static void main(String[] args) {
        BigDecimal principal = new BigDecimal("1000.00"); // 本金
        BigDecimal interestRate = new BigDecimal("0.05"); // 税率

        // 计算税额: 税额 = 本金 * 税率
        BigDecimal interest = principal.multiply(interestRate);

        // 计算价税合计: 总额 = 本金 + 税额
        BigDecimal totalAmount = principal.add(interest).setScale(2, RoundingMode.HALF_UP);

        System.out.println("Total amount after one year: " + totalAmount); // 输出价税合计
    }
}

总结

最后非常感谢您阅读 BigDecimal 的基操。我希望上述的信息和代码示例能够帮助您更好地理解和使用 BigDecimal,特别是在需要高精度计算的场景中。无论您是在处理复杂的金融计算、需要处理精确的用户输入,还是简单地希望避免浮点数带来的精度问题,BigDecimal 都是一个非常有力的工具。

如果您在日常开发中遇到任何关于 Java 或 BigDecimal 的问题,欢迎随时向我咨询。再次感谢您的阅读,祝您编程愉快,项目顺利!

相关推荐
海绵波波10711 分钟前
flask后端开发(1):第一个Flask项目
后端·python·flask
AI人H哥会Java3 小时前
【Spring】控制反转(IoC)与依赖注入(DI)—IoC容器在系统中的位置
java·开发语言·spring boot·后端·spring
凡人的AI工具箱3 小时前
每天40分玩转Django:Django表单集
开发语言·数据库·后端·python·缓存·django
奔跑草-3 小时前
【数据库】SQL应该如何针对数据倾斜问题进行优化
数据库·后端·sql·ubuntu
中國移动丶移不动3 小时前
Java 并发编程:原子类(Atomic Classes)核心技术的深度解析
java·后端
Q_19284999065 小时前
基于Spring Boot的旅游推荐系统
spring boot·后端·旅游
愤怒的代码5 小时前
Spring Boot对访问密钥加密解密——RSA
java·spring boot·后端
美美的海顿5 小时前
springboot基于Java的校园导航微信小程序的设计与实现
java·数据库·spring boot·后端·spring·微信小程序·毕业设计
愤怒的代码5 小时前
Spring Boot中幂等性的应用
java·spring boot·后端
xiaocaibao7775 小时前
编程语言的软件工程
开发语言·后端·golang