JDK-4851777 : Add BigDecimal sqrt method
  • Type: Enhancement
  • Component: core-libs
  • Sub-Component: java.math
  • Affected Version: 5.0
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2003-04-22
  • Updated: 2019-11-04
  • Resolved: 2016-05-20
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
9 b120Fixed
Related Reports
CSR :  
Duplicate :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
A sqrt routine for BigDecimal is a part of jsr13.

From the IEEE 754-2008 standard for floating-point arithmetic, for a decimal square root of x the preferred exponent is floor(Q(x)/2) where Q(x) is the exponent of the representation of x. In BigDecimal terminology, Q(x) == -x.scale() since scale() is the negated exponent. (See IEEE 754-2008 sections 5.2 for decimal exponent calculation and 5.4.1 for Arithmetic Operations like sqrt.) For the addition operation, since the preferred scale is max(addend.scale(), augend.scale()), adding a zero with the right scale would be one way to generate the desired representation of the result.

This hack seems to work to some degree: public static BigDecimal sqrtBigDecimal(BigDecimal n) { if (n.compareTo(BigDecimal.ZERO) == 0) { return BigDecimal.ZERO; } else if (n.compareTo(BigDecimal.ONE) == 0) { return BigDecimal.ONE; } else if (n.signum() < 0) { throw new ArithmeticException("Negative BigDecimal"); } MathContext mc = new MathContext(34, RoundingMode.HALF_UP); BigDecimal xk; BigDecimal delta; Double d = n.doubleValue(); double minSqr = Double.MIN_VALUE*Double.MIN_VALUE; if (!d.isInfinite() && d > minSqr) { double dSqrt = Math.sqrt(d); delta = new BigDecimal(BigInteger.ONE, mc.getPrecision()); xk = BigDecimal.valueOf(dSqrt); } else { int scale = n.scale(); BigInteger value = n.unscaledValue(); if (scale != 0) { if (scale % 2 != 0) { scale++; value = value.multiply(BigInteger.TEN); } scale /= 2; } int precision = scale < 0 ? mc.getPrecision() : scale + mc.getPrecision(); delta = new BigDecimal(BigInteger.ONE, precision); int rightShift = value.bitCount()/2; xk = new BigDecimal(value.shiftRight(rightShift), scale); } BigDecimal two = BigDecimal.valueOf(2); BigDecimal xk1 = n.divide(xk, mc).add(xk).divide(two, mc); while (xk1.subtract(xk).abs().compareTo(delta) > 0) { xk = xk1; xk1 = n.divide(xk, mc).add(xk).divide(two, mc); } return xk1; }

That is definitely a better approach. I think my concentration was so focused on BigInteger, which cannot usually be approximated by a double, that I overlooked this idea. It will not work however if bd.doubleValue() == Double.POSITIVE_INFINITY.

My first reaction to get an initial guess on a BigDecimal.sqrt Newton iteration would be BigDecimal bd = ... BigDecimal x0 = new BigDecimal(Math.sqrt(bd.doubleValue())); Creating a BigInteger for a large in magnitude BigDecimal could create a very large, unwieldy object while creating a BigDecimal from a double should be more bounded in size. (The IEEE 754-2008 standard should be consulted to see if it offers any guidance on the preferred exponent of a square root operation.)

If this method were to be implemented via Newton iteration, then assuming that a BigInteger.sqrt() method were available, one means of computing the initial estimate x0 of the iteration is: BigDecimal bd; // BigDecimal of which the square root is to be computed. int scale = bd.scale(); BigInteger value = bd.unscaledValue(); if (scale != 0) { if (scale % 2 != 0) { scale++; value = value.multiply(BigInteger.TEN); } scale /= 2; } BigDecimal x0 = new BigDecimal(value.sqrt(), scale);

CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: mustang

EVALUATION Part of jsr13. ###@###.### 2003-04-21 No longer being included in jsr13; should be considered for a future release. ###@###.### 2003-09-08