I tried calculating the sum of the digits of square root of integers below a particular input with large precison (upto 10000) using BigInteger.
public class SquareRootHackerRankJarvis {
static BigInteger limit;
static BigInteger a;
static BigInteger b;
private static BigInteger squareroot(int n, BigInteger ten,
BigInteger hundred, BigInteger five) {
a = BigInteger.valueOf(n * 5);
b = BigInteger.valueOf(5);
while (b.compareTo(limit) == -1) {
if (a.compareTo(b) != -1) {
a = a.subtract(b);
b = b.add(ten);
} else {
a = a.multiply(hundred);
b = (b.divide(ten)).multiply(hundred).add(five);
}
}
return b.divide(hundred);
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int N = scanner.nextInt();
int P = scanner.nextInt();
int sum = 0;
int p = 1;
BigInteger ten = BigInteger.valueOf(10);
BigInteger hundred = BigInteger.valueOf(100);
BigInteger five = BigInteger.valueOf(5);
limit = ten.pow(P + 1);
for (int i = 1; i <= N; i++) {
if (p * p == i) {
p++;
continue;
}
BigInteger x = squareroot(i, ten, hundred, five);
char[] digits = x.toString().toCharArray();
for (int j = 0; j <= P - 1; j++) {
sum += Character.getNumericValue(digits[j]);
}
}
System.out.println(sum);
scanner.close();
}}
The performance was quite bad and it eats a lot of time for precision 10000 (P). I read in another post that MutableBigInteger performs well ahead of BigInteger, since it is mutable.Therefore I refactored the code using MutableBigInteger.
public class SquareRootHackerRankJarvisMutableBigInteger {
static Object limit;
static Object a;
static Object b;
public static void main(String[] args) throws NoSuchMethodException,
SecurityException, InstantiationException, IllegalAccessException,
IllegalArgumentException, InvocationTargetException,
ClassNotFoundException {
Scanner scanner = new Scanner(System.in);
int N = scanner.nextInt();
int P = scanner.nextInt();
int sum = 0;
int p = 1;
BigInteger tenB = BigInteger.valueOf(10);
Class<?> c = Class.forName("java.math.MutableBigInteger");
Constructor<?> constructor = c.getDeclaredConstructor(int.class);
constructor.setAccessible(true);
Constructor<?> constructor1 = c
.getDeclaredConstructor(BigInteger.class);
constructor1.setAccessible(true);
Method add = c.getDeclaredMethod("add", new Class[] { c });
Method subtract = c.getDeclaredMethod("subtract", new Class[] { c });
Method mul = c.getDeclaredMethod("mul", new Class[] { int.class, c });
Method divide = c.getDeclaredMethod("divide", new Class[] { long.class,
c });
Method compare = c.getDeclaredMethod("compare", new Class[] { c });
Method copyValue = c.getDeclaredMethod("copyValue", new Class[] { c });
add.setAccessible(true);
subtract.setAccessible(true);
mul.setAccessible(true);
divide.setAccessible(true);
compare.setAccessible(true);
copyValue.setAccessible(true);
Object ten = constructor.newInstance(10);
Object five = constructor.newInstance(5);
Object v = constructor.newInstance(0);
Object sqrt = constructor.newInstance(0);
limit = constructor1.newInstance(tenB.pow(P + 1));
for (int i = 1; i <= N; i++) {
if (p * p == i) {
p++;
continue;
}
a = constructor.newInstance(i * 5);
b = constructor.newInstance(5);
while (((Integer) compare.invoke(b, limit)).intValue() == -1) {
if (((Integer) compare.invoke(a, b)).intValue() != -1) {
subtract.invoke(a, b);
add.invoke(b, ten);
} else {
mul.invoke(a, 100, v);
copyValue.invoke(a, v);
divide.invoke(b, 10, v);
mul.invoke(v, 100, b);
add.invoke(b, five);
}
}
divide.invoke(b, 100, sqrt);
char[] digits = sqrt.toString().toCharArray();
for (int j = 0; j <= P - 1; j++) {
sum += Character.getNumericValue(digits[j]);
}
}
System.out.println(sum);
scanner.close();
}}
But still i could not see any performance improvement.Can anyone please give me any suggestions about the proper usage of MutableBigInteger with Reflection?