Skip to content

Commit a0e0b2d

Browse files
committed
8370057: Correct scale handling of BigDecimal.sqrt
Reviewed-by: rgiulietti
1 parent 869112e commit a0e0b2d

File tree

2 files changed

+7
-6
lines changed

2 files changed

+7
-6
lines changed

src/java.base/share/classes/java/math/BigDecimal.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@
154154
* <tr><th scope="row">Subtract</th><td>max(minuend.scale(), subtrahend.scale())</td>
155155
* <tr><th scope="row">Multiply</th><td>multiplier.scale() + multiplicand.scale()</td>
156156
* <tr><th scope="row">Divide</th><td>dividend.scale() - divisor.scale()</td>
157-
* <tr><th scope="row">Square root</th><td>radicand.scale()/2</td>
157+
* <tr><th scope="row">Square root</th><td>ceil(radicand.scale()/2.0)</td>
158158
* </tbody>
159159
* </table>
160160
*
@@ -2113,7 +2113,7 @@ public BigDecimal[] divideAndRemainder(BigDecimal divisor, MathContext mc) {
21132113
* with rounding according to the context settings.
21142114
*
21152115
* <p>The preferred scale of the returned result is equal to
2116-
* {@code this.scale()/2}. The value of the returned result is
2116+
* {@code Math.ceilDiv(this.scale(), 2)}. The value of the returned result is
21172117
* always within one ulp of the exact decimal value for the
21182118
* precision in question. If the rounding mode is {@link
21192119
* RoundingMode#HALF_UP HALF_UP}, {@link RoundingMode#HALF_DOWN
@@ -2174,7 +2174,7 @@ public BigDecimal sqrt(MathContext mc) {
21742174

21752175
// The code below favors relative simplicity over checking
21762176
// for special cases that could run faster.
2177-
final int preferredScale = this.scale/2;
2177+
final int preferredScale = Math.ceilDiv(this.scale, 2);
21782178

21792179
BigDecimal result;
21802180
if (mc.roundingMode == RoundingMode.UNNECESSARY || mc.precision == 0) { // Exact result requested

test/jdk/java/math/BigDecimal/SquareRootTests.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -348,7 +348,7 @@ private static int lowPrecisionPerfectSquares() {
348348

349349
for (int scale = 0; scale <= 4; scale++) {
350350
BigDecimal scaledSquare = square.setScale(scale, RoundingMode.UNNECESSARY);
351-
int expectedScale = scale/2;
351+
int expectedScale = Math.ceilDiv(scale, 2);
352352
for (int precision = 0; precision <= 5; precision++) {
353353
for (RoundingMode rm : RoundingMode.values()) {
354354
MathContext mc = new MathContext(precision, rm);
@@ -582,7 +582,8 @@ public static BigDecimal sqrt(BigDecimal bd, MathContext mc) {
582582
// The code below favors relative simplicity over checking
583583
// for special cases that could run faster.
584584

585-
int preferredScale = bd.scale()/2;
585+
int preferredScale = Math.ceilDiv(bd.scale(), 2);
586+
586587
BigDecimal zeroWithFinalPreferredScale =
587588
BigDecimal.valueOf(0L, preferredScale);
588589

0 commit comments

Comments
 (0)