蓝易云cdn:BigInt和BigDec的使用
Java中BigInteger和BigDecimal的使用详解 🔢
Java的基本数值类型存在天然的局限——long 最大只能表示约19位整数,double 在小数运算中存在精度丢失问题。当业务涉及超大整数运算或高精度金融计算时,BigInteger 和 BigDecimal 就是不可替代的选择。

一、BigInteger:处理超大整数 💪
BigInteger 位于 java.math 包下,可以表示任意大小的整数,不受位数限制。
创建方式:
BigInteger a = new BigInteger("99999999999999999999");
BigInteger b = BigInteger.valueOf(1234567890L);
解释: 超出 long 范围的数值必须用字符串形式传入构造方法,这是最常用的创建方式。如果数值在 long 范围以内,可以用 valueOf 静态方法创建,内部有小值缓存,性能更优。
基本运算:
BigInteger x = new BigInteger("100000000000000000000");
BigInteger y = new BigInteger("200000000000000000000");
BigInteger sum = x.add(y); // 加法
BigInteger diff = y.subtract(x); // 减法
BigInteger prod = x.multiply(y); // 乘法
BigInteger quot = y.divide(x); // 除法
BigInteger mod = y.mod(x); // 取模
BigInteger pow = x.pow(3); // 幂运算
解释: BigInteger是不可变对象,所有运算都返回新的BigInteger实例,原始对象不会被修改。这一点和String的设计理念一致。绝对不能用 +、-、*、/ 运算符,编译器不会报错但结果完全不对(实际上会编译报错),必须调用对应的方法 ⚠️。
比较大小:
int cmp = x.compareTo(y);
// cmp < 0 表示 x < y
// cmp == 0 表示 x == y
// cmp > 0 表示 x > y
boolean isEqual = x.equals(y); // 判断是否相等
解释: 比较两个BigInteger不能用 ==(那只是比较对象引用地址),必须用 compareTo 或 equals 方法。compareTo 返回负数、零、正数分别代表小于、等于、大于,在排序和条件判断中非常常用。
二、BigDecimal:高精度小数运算 💰
先看一个经典问题:
System.out.println(0.1 + 0.2); // 输出:0.30000000000000004
解释:double 采用IEEE 754二进制浮点数标准,0.1和0.2在二进制中都是无限循环小数,存储时必然产生截断误差。这在金融、财务等场景中是绝对不可接受的,一分钱的偏差都可能导致对账失败。BigDecimal 正是为解决这个问题而生 🎯。
正确的创建方式:
// 推荐:字符串构造
BigDecimal a = new BigDecimal("0.1");
BigDecimal b = new BigDecimal("0.2");
// 推荐:valueOf方法
BigDecimal c = BigDecimal.valueOf(0.1);
// 危险:double构造(千万避免!)
BigDecimal d = new BigDecimal(0.1);
// d的实际值是0.1000000000000000055511151231257827021181583404541015625
解释: 这是使用BigDecimal最关键的一条规则——永远不要用 new BigDecimal(double) 构造方法。因为传入的double值本身就已经丢失精度了,BigDecimal只是精确地记录下了那个"不精确的值"。字符串构造和 valueOf 方法都能保证精度正确。阿里巴巴Java开发手册也将此列为强制规范 🚫。
四则运算:
BigDecimal x = new BigDecimal("10.5");
BigDecimal y = new BigDecimal("3");
BigDecimal sum = x.add(y); // 13.5
BigDecimal diff = x.subtract(y); // 7.5
BigDecimal prod = x.multiply(y); // 31.5
解释: 加减乘运算非常直观,调用对应方法即可,返回新的BigDecimal对象。
除法必须指定精度:
// 错误写法:可能抛出ArithmeticException
BigDecimal wrong = x.divide(y);
// 正确写法:指定保留位数和舍入规则
BigDecimal right = x.divide(y, 2, RoundingMode.HALF_UP);
// 结果:3.50
解释: 当除法结果是无限小数时(比如10.5÷3=3.5,但有些情况下结果是无限循环小数),如果不指定精度,BigDecimal无法表示而直接抛异常。第二个参数 2 表示保留2位小数,第三个参数 RoundingMode.HALF_UP 就是我们常说的"四舍五入"。这是BigDecimal使用中最常见的坑,务必养成除法必带精度的习惯 ⚡。
常用舍入模式:
| 模式 | 含义 |
|---|---|
HALF_UP |
四舍五入(最常用) |
HALF_DOWN |
五舍六入 |
CEILING |
向正无穷方向进位 |
FLOOR |
向负无穷方向截断 |
DOWN |
直接截断,不进位 |
比较大小的陷阱:
BigDecimal m = new BigDecimal("1.0");
BigDecimal n = new BigDecimal("1.00");
System.out.println(m.equals(n)); // false !
System.out.println(m.compareTo(n)); // 0(相等)