必须用biginteger和bigdecimal当数字超出long/double安全范围或需精确小数运算(如金融、科学计算);前者用于任意精度整数,后者用于任意精度十进制小数。

Java里什么时候必须用 BigInteger 和 BigDecimal
当数字超出 long 或 double 的安全表示范围,或者需要精确小数运算(比如钱、利率、科学计算)时,BigInteger 和 BigDecimal 不是“可选”,而是唯一靠谱的选择。用 int/long 算阶乘 50 就溢出;用 double 算 0.1 + 0.2 得到 0.30000000000000004——这不是 bug,是二进制浮点数的固有限制。
常见错误现象:
• long result = Long.MAX_VALUE * 2; 编译不报错,但结果是负数(静默溢出)
• double price = 19.99 + 0.01; 输出 19.999999999999996,导致金额校验失败
• 金融系统用 float 存余额,几轮加减后误差累积不可控
-
BigInteger专用于任意精度整数:密码学、大质数生成、超长 ID 运算 -
BigDecimal专用于任意精度十进制小数:计费、财务报表、税率计算 - 别用
BigDecimal(double)构造器——它会继承double的精度污染,比如new BigDecimal(0.1)实际存的是0.1000000000000000055511151231257827021181583404541015625
BigDecimal 创建和比较必须绕开的坑
创建要传字符串,比较不能用 == 或 .equals() 直接比值:
- ✅ 正确写法:
new BigDecimal("19.99")、BigDecimal.valueOf(1999).divide(BigDecimal.valueOf(100)) - ❌ 错误写法:
new BigDecimal(19.99)(传 double)、big1 == big2(引用比较)、big1.equals(big2)(equals()同时比较值和精度,new BigDecimal("1.0").equals(new BigDecimal("1.00"))返回false) - 比较请统一用
.compareTo():返回 -1/0/1,语义清晰且忽略精度差异 - 做除法必须指定
scale和舍入模式,否则遇到除不尽直接抛ArithmeticException,例如:amount.divide(rate, 2, RoundingMode.HALF_UP)
BigInteger 运算没有隐式类型转换,所有操作都得手动转
BigInteger 是不可变对象,所有运算(add、multiply、modPow)都返回新实例,原变量不变。而且它不支持 +、* 这类操作符重载,也不能和基本类型混算。
WOC是基于zend framework1.6框架所开发的一款开源简易网站运营管理系统。它允许进行网站管理、主机管理、域名管理、数据库管理、邮箱管理以及用户管理、角色管理、权限管理等一系列功能,适合中小企业进行网站运营管理。目前版本为V1.2,新版本正在开发中,同时欢迎大家参与到开发中来! WOC升级说明: 1.1在1.0的基础上进行了代码规范并增加了配置数据缓存,以提高访问速度 注意:升级时要重
立即学习“Java免费学习笔记(深入)”;
- ❌ 错误:
BigInteger a = ...; a += 5;(编译失败);a + b(语法错误) - ✅ 正确:
a.add(BigInteger.valueOf(5))、a.multiply(b)、a.modPow(exp, mod)(模幂,密码常用) - 从基本类型转:优先用
BigInteger.valueOf(long)(缓存小整数),避免new BigInteger(String)带解析开销 - 转回基本类型要小心:
intValueExact()和longValueExact()在溢出时抛异常,比静默截断更安全
性能和线程安全的真实代价
BigInteger 和 BigDecimal 是对象,不是原生类型,每次运算都分配新对象,频繁使用会明显增加 GC 压力。它们线程安全(不可变),但不代表“高并发下无代价”。
- 高频场景(如实时风控计算)慎用:先评估是否真需要全精度——有时用
long存“分”、int存“万分之一”更轻量 -
BigDecimal的toString()开销比double大得多,日志里打它前考虑toPlainString()(避免科学计数法)或缓存格式化结果 - 多线程共享同一个
BigDecimal实例没问题,但别为了“复用”而把计算中间结果设为静态变量——容易引发逻辑耦合和精度污染 - 序列化时注意:
BigDecimal的scale会被保留,new BigDecimal("1.00")和new BigDecimal("1")序列化后是不同的字节流
最常被忽略的一点:精度不是越高越好。BigDecimal 的 scale 和 RoundingMode 必须跟业务规则对齐——银行结息按“四舍六入五成双”,税务计算可能要求“向上取整到分”,这些不是库能替你决定的。









