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.
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.
25-09-2015
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;
}
24-09-2015
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.
24-09-2015
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.)
22-09-2015
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);
22-09-2015
CONVERTED DATA
BugTraq+ Release Management Values
COMMIT TO FIX:
mustang
14-06-2004
EVALUATION
Part of jsr13.
###@###.### 2003-04-21
No longer being included in jsr13; should be considered for a future release.
###@###.### 2003-09-08