Is there a library that will find the square root of a BigInteger? I want it computed offline - only once, and not inside any loop. So even computationally expensive solutio
Here's a solution that does not use BigInteger.multiply or BigInteger.divide:
private static final BigInteger ZERO = BigInteger.ZERO;
private static final BigInteger ONE = BigInteger.ONE;
private static final BigInteger TWO = BigInteger.valueOf(2);
private static final BigInteger THREE = BigInteger.valueOf(3);
/**
* This method computes sqrt(n) in O(n.bitLength()) time,
* and computes it exactly. By "exactly", I mean it returns
* not only the (floor of the) square root s, but also the
* remainder r, such that r >= 0, n = s^2 + r, and
* n < (s + 1)^2.
*
* @param n The argument n, as described above.
*
* @return An array of two values, where the first element
* of the array is s and the second is r, as
* described above.
*
* @throws IllegalArgumentException if n is not nonnegative.
*/
public static BigInteger[] sqrt(BigInteger n) {
if (n == null || n.signum() < 0) {
throw new IllegalArgumentException();
}
int bl = n.bitLength();
if ((bl & 1) != 0) {
++ bl;
}
BigInteger s = ZERO;
BigInteger r = ZERO;
while (bl >= 2) {
s = s.shiftLeft(1);
BigInteger crumb = n.testBit(-- bl)
? (n.testBit(-- bl) ? THREE : TWO)
: (n.testBit(-- bl) ? ONE : ZERO);
r = r.shiftLeft(2).add(crumb);
BigInteger d = s.shiftLeft(1);
if (d.compareTo(r) < 0) {
s = s.add(ONE);
r = r.subtract(d).subtract(ONE);
}
}
assert r.signum() >= 0;
assert n.equals(s.multiply(s).add(r));
assert n.compareTo(s.add(ONE).multiply(s.add(ONE))) < 0;
return new BigInteger[] {s, r};
}