java 9 及之后版本的 bigdecimal 新增了 sqrt(mathcontext mc) 实例方法,用于计算指定精度下的非负数平方根,需显式传入 mathcontext 控制精度与舍入模式,不支持无参调用,结果精度由 mathcontext 决定。

Java 9 及之后版本的 BigDecimal 仍然没有内置的 sqrt() 方法(该方法直到 Java 9 都未被加入标准库,实际是在 Java 9 中首次引入,但仅作为 MathContext 感知的静态方法,且需注意使用限制)。
Java 9 新增的 sqrt() 方法用法
Java 9 在 BigDecimal 类中新增了 sqrt(MathContext mc) 实例方法,用于计算指定精度下的平方根:
- 它要求输入值必须为非负数,否则抛出
ArithmeticException(如 -1); - 必须显式传入
MathContext,用于控制精度(位数)和舍入模式; - 不支持无参数调用(即没有
sqrt()无参重载); - 结果精度 ≈ 输入精度 / 2,但最终由
MathContext决定,不是简单截断,而是按指定舍入规则计算。
正确调用示例
以下代码在 Java 9+ 中可安全运行:
BigDecimal x = new BigDecimal("2.0");
MathContext mc = new MathContext(50, RoundingMode.HALF_UP);
BigDecimal sqrtX = x.sqrt(mc); // 得到 50 位精度的 √2
注意:MathContext 的精度指**有效数字位数**,不是小数位数。例如 new MathContext(10) 表示结果最多保留 10 个有效数字。
兼容低版本或需要更高控制时的替代方案
若需在 Java 8 或更早环境运行,或要自定义收敛条件、避免 sqrt() 对某些边界值(如 0、极小数)的潜在问题,可采用牛顿迭代法手动实现:
- 初始猜测值建议用
BigDecimal.valueOf(Math.sqrt(x.doubleValue()))快速逼近; - 迭代公式:
next = current.subtract(current.pow(2).subtract(x).divide(current.multiply(BigDecimal.valueOf(2)), mc)); - 循环直到前后两次结果在给定精度内差异小于阈值(如
abs(next.subtract(current)).compareTo(epsilon) ); - 务必全程使用同一
MathContext,尤其在divide()中不可省略,否则可能抛NumberFormatException(无限循环小数无法精确表示)。
常见陷阱提醒
使用 sqrt() 时容易忽略的关键点:
- 传入
MathContext的精度不能过低(如设为 1),否则结果可能完全失真; - 对整数开方(如
new BigDecimal("100").sqrt(mc))仍返回BigDecimal,不会自动转为整型; -
sqrt()不处理科学计数法字符串的隐式精度丢失——构造BigDecimal时应优先用字符串而非 double 字面量(如用"0.1"而非0.1); - Java 9 的
sqrt()在内部使用类似牛顿法的算法,但具体实现不公开,行为以文档和测试为准,生产环境建议加单元测试覆盖边界值。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











