I have two integers x and y.
Rule:
If x > y : x = x - y and y = 2 * y;
If y > x : y = y - x and x = 2 * x;
If y == x : not infinite loop
The question is, will the two integers be an infinite loop or not?
Here is my code:
private static boolean IsPairLoop(int first, int second)
{
boolean loop = false;
HashMap<Integer, Integer> round_record = new HashMap<>();
int[] first_round = new int[]{first, second};
while ((first_round[0] != -1 && first_round[1] != -1))
{
if (round_record.containsKey(first_round[0]))
{
loop = true;
break;
}
round_record.put(first_round[0], first_round[1]);
PlayRound(first_round);
}
return loop;
}
private static void PlayRound(int[] round)
{
if (round[0] > round[1])
{
round[0] -= round[1];
round[1] += round[1];
}
else if (round[0] < round[1])
{
round[1] -= round[0];
round[0] += round[0];
}
else
{
round[0] = -1;
round[1] = -1;
}
}
This works fine for small integers. However, this is painfully slow when the integer difference is really large. Integer range is 1 to 2^30 for both x and y. What can I do to make this fast even when the integers difference is large?
In this problem, the sum x + y is invariant, and if it is odd, x == y is impossible.
Then if x and y have the same parity, after one iteration they become both even and remain so, and the problem is unchanged if you divide both by 2.
Hence the "instantaneous" solution:
while (x + y) & 1 == 0:
if x == y:
print "Not infinite"
break
if x > y:
x= (x - y) / 2
else:
y= (y - x) / 2
else:
print "Infinite"
As one of the arguments loses at least one bit on every iteration, there are never more than 64 iterations for 32 bits integers (and in practice much less, most of the time 0 !).
A variant is possible and can make sense for bignumbers:
if x == y, conclude finite.
if x and y have a different number of trailing zeroes, conclude infinite.
otherwise, discard the trailing zeroes and perform the reduction according to x > y or y > x and loop.
Instead of using a hashmap, use Floyd's cycle detection algorithm. Not only will this avoid large memory use, it will also avoid costly boxing and unboxing between int and Integer.
A second optimisation is to re-write the recurrence relations via a change of variables:
s = x+y
t = x-y
Then the recurrence relations become:
if t=0, stop
if t>0, s'=s, t'=2t-s
if t<0, s'=s, t'=2t+s
Note in this formulation, only the t variable changes.
The code (untested) will look something like this:
private static int step(int s, int t) {
if (t>0) return 2*t - s;
if (t<0) return 2*t + s;
return 0;
}
private static boolean IsPairLoop(int first, int second) {
int s = first+second;
int t_slow = first-second;
int t_fast = t_slow;
while(t_slow != t_fast) {
t_slow = step(s, t_slow);
t_fast = step(s, step(s, s_fast));
}
return t_slow != 0;
}
You may need to replace int with long if first+second can overflow.
I think, given the preconditions, you never get a t that goes off to infinity (since it's always true that |t| < s). But you may wish to double-check, perhaps adding some sort of assertion into your code.
Let’s work backwards a bit. What can produce x == y? The difference between the previous x and y has to be equal to twice the smaller of the two, i.e. the larger has to be three times the smaller. Things that don’t loop infinitely so far:
{n, n}
{n, 3n}
Where can {n, 3n} come from? Either
n is a difference a − b for some a > b, and 3n = 2b
3(a − b) = 2b
3a − 3b = 2b
3a = 5b
a = 5/3 b
A pair {m, 5/3 m} is something that produces {n, 3n} on the next step. (m has to be divisible by 3, but that’s okay.)
3n is a difference a − b for some a > b, and n = 2b
(a − b)/3 = 2b
a − b = 6b
a = 7b
A pair {m, 7m} is the only other thing that can produce {n, 3n} on the next step.
An updated list:
{n, n}
{n, 3n}
{n, 7n}
{n, 5/3 n}
Seems like a good time to generalize those last steps.
{n, qn} happens when:
n is a difference a − b for some a > b, and qn = 2b
q(a − b) = 2b
qa − qb = 2b
qa = (2 + q)b
a = (2 + q)/q b
or qn is a difference a − b for some a > b, and n = 2b
(a − b)/q = 2b
a − b = 2qb
a = (2q + 1)b
So if q = m/n is in the list, these are also in the list:
(2n + m)/m
(2m + n)/n
q = 1 generates:
(2 + 1)/1 = 3
2×1 + 1 = 3
q = 3 generates:
3
(2 + 3)/3 = 5/3
2×3 + 1 = 7
q = 5/3 generates:
3
5/3
7
(2 + 5/3)/(5/3) = (6 + 5)/5 = 11/5
(2×5/3) + 1 = 10/3 + 1 = 13/3
q = 7 generates:
3
5/3
7
11/5
13/3
(2 + 7)/7 = 9/7
2×7 + 1 = 15
Hmm… that’s pretty interesting. Let’s sort the list by the numerator:
3/1
5/3
7/1
9/7
11/5
13/3
15/1
Based on that pattern, I’d expect 17/15 to come next. Generating a list sorted by denominator with a computer:
3/1
7/1
15/1
31/1
63/1
5/3
13/3
29/3
61/3
11/5
27/5
59/5
9/7
25/7
57/7
23/9
55/9
21/11
53/11
19/13
51/13
17/15
49/15
47/17
45/19
43/21
41/23
39/25
37/27
35/29
33/31
Looks an awful lot like m/n where n is odd, m > n, and m + n is a power of two. So one way to optimize your algorithm would be:
private static boolean isPairLoop(int first, int second)
{
if (first == second) return false;
if (first > second) return isPairLoop(second, first);
if (first == 0) return true;
int d = gcd(first, second);
return Integer.bitCount(first / d + second / d) != 1;
}
private static int gcd(int a, int b)
{
return b == 0 ? a : gcd(b, a % b);
}
Takes quadratic time on the number of digits on bigints.
Now you just have to prove that it works. I hope it works.
Related
good day,
what is the best way to implement the below function in java:
mod11(x) which calculates x mod 11, we assume x is either an integer or a formula. For example, mod11(14) returns 3, and mod11(3*7-30) returns 2.
I tried the below but it didn't work:
`
public static int PositiveMod(int value, int mod)
{
return ((value % mod + mod) % mod);
}
`
`
public static double PositiveMod(double value, double mod)
{
return ((value % mod + mod) % mod);
}
`
for example, i expect ((-7+1)/20) mod 11 to give out 3 but instead it gave me 10.7
like below
i = ((-7+1)/20) mod 11 = -6/9 mod 11 = 5*5 mod 11 = 3
I wrote two examples how to use it mathematical mod mathMod method and also default mod faultModCalJava mod. They will give the same result for positive numbers but for negative they have different output. More information here:
https://en.wikipedia.org/wiki/Modulo_operation
public class MainClass2 {
public static void main(String[] args) {
System.out.println("Math mod:" + mathMod(14, 11));
System.out.println("Math mod:" + mathMod((3 * 7 - 30), 11));
System.out.println("Math mod:" + mathMod(-13, 10));
System.out.println("Default Java mod: " + defaultModCalJava(14, 11));
System.out.println("Default Java mod: " + defaultModCalJava((3 * 7 - 30), 11));
System.out.println("Default Java mod:" + defaultModCalJava(-13, 10));
}
private static int mathMod(int a, int m) {
int positiveM = Math.abs(m);
int result = a % positiveM;
if (result < 0) {
result = result + positiveM;
}
return result;
}
private static int defaultModCalJava(int a, int m) {
return a % m;
}
}
Output:
Math mod:3
Math mod:2
Math mod:7
Default Java mod: 3
Default Java mod: -9
Default Java mod:-3
Your question is confusing.. the % operator is already the modulus operator, also known as remainder. ... so 14 % 11 = 3 is the same as mod11(14) = 3. There is no need to implement it as a new function.
In your equation, ((-7+1)/20) = -0.3, Its not clear why you would expect 3.
11 - 0.3 is 10.7, so that is where that answer comes from.
% is not a modulus operator. It is a remainder operator and behaves as one would expect a remainder operator to behave.
System.out.println(-10 % 3); // -3 r -1 since 3 * -3 + -1 == -10
System.out.println(10 % -3); // -3 r 1 since -3 * -3 + 1 == 10
System.out.println(-10 % -3);// 3 r -1 since 3 * -3 + -1 == -10
System.out.println(10 % 3); // 3 r 1 since 3 * 3 + 1 == 10
prints as expected
-1
1
-1
1
A true mod function for n = x mod(m) says there is some k where x - n = km
n = 20 mod(3) = 2 and k = 6 20 - 2 = 6*3
n = 20 mod(3) = -1 and k = 7 20 -(-1) = 3*7
The complete set of residues for any mod function is infinite and for the above is
n = x - mk for any integral value of k
So for the above the complete residue set would be n = 20 - 3k. Any value returned would be a legitimate result. The remainder function is simply a subset of size one of the aforementioned set of residues.
Having said that, this may help. This mod function simply corrects to the smallest positive value, assuming a positive modulus.
Mod mod11 = Mod.forModulus(11);
int k = mod11.of(-3);
System.out.println(k);
Mod mod121 = Mod.forModulus(121);
k = mod121.of(-12);
System.out.println(k);
prints
8
109
Here is a way to create mod function that just takes the target argument.
interface Mod {
int of(int value);
static Mod forModulus(int mod) {
return v-> {
int u = v % mod;
return u < 0 ? u + mod : u;
};
}
}
The above may need some tweaking either because I misunderstood your issue or because the mod function needs to be more complex to satisfy your congruency relationships.
What is Cardano Triplet ?
If a set of any three positive integers, let's say a, b and c satisfies the condition
cbrt(a + b(sqrt(c)) + cbrt(a - b(sqrt(c)) == 1
Explanation.
if sum of Cubic Root of a + (b * square root of c) and Cubic root of a - (b * square root of c) equals 1 then (a, b, c) is said to be a Cardano triplet.
cbrt represents Cubic Root and sqrt means Square Root.
A integer n will be given, so the numbers a, b and c that we take when added should be lesser than or equal to n.
In short a + b + c <= n.
Constraint : n <= 2^31 -1.
Problem
I've already done something which finds out the correct triplets but when the value of n is greater than 1000 the program runs forever.
public static void cardanoTriplets(long n) {
DecimalFormat decimalFormat = new DecimalFormat("#.###");
long numberOfPairs = 0;
for (long a = 0; a <= n; a++) {
for (long b = 0; b <= n; b++) {
for (long c = 0; c <= (n - a - b); c++) {
if ((a + b + c) == n) {
double val = b * Math.sqrt(c);
double LHS = Double.parseDouble(decimalFormat.format(Math.cbrt(a + val)));
double RHS = Double.parseDouble(decimalFormat.format(Math.cbrt(a - val)));
double addedVal = LHS + RHS;
//System.out.println("RHS and LHS -: ( " + RHS + " , " + LHS + " )");
if (addedVal == 1.0d) {
numberOfPairs++;
//System.out.println(a);
//System.out.println(b);
//System.out.println(c + "\n");
}
}
}
}
}
System.out.println(numberOfPairs);
}
Results
When I pass the value of n as 8, on average the time taken to find the cardano triplet is 31ms and sometimes as low as 16ms. The result was accurate and the result is just one and the triplet is (2, 1, 5).
But when I pass the value of n as 1000, it increases to about 1015ms and the result are not as accurate. It misses out almost 19 triplets. Total number of triplets are 149 for n == 1000.
When the value of n > 1000, let's say 5000, it took 29271ms which is 29 seconds approx and the triplets found are 3364.
Is there any way to reduce time taken to a reasonable amount like less than 5 seconds ?
If so how ?
My Device Specs :
Processor : AMD Ryzen 5 3500U Quad Core
RAM : 8 GB
IDE used : IntelliJ IDEA v2021.2.3 (Community Edition)
Thank you :)
This is a number-theoretical problem; using an imprecise floating point is obviously wrong.
The correct solution requires some math insight. Cardano's name is a great hint.
The expression
cbrt(a + b(sqrt(c)) + cbrt(a - b(sqrt(c))
describes a root of a certain cubic equation. Specifically, the roots of an equation
x^3 + px - q = 0
are
cbrt(q/2 + sqrt((q/2)^2 + (p/3)^3)) + cbrt(q/2) - sqrt(q/2)^2 + (p/3)^3))
Comparing with your problem statement, conclude that a = q/2, and c*b^2 = (q/2)^2 + (p/3)^3
Since a is an integer, q must be even, and since b, c are also integers, p must be divisible by 3. Therefore we are interested in the equations
x^3 + 3ux - 2a = 0
having 1 as a root. That narrows the problem down to searching u, v such that 1 + 3u - 2a = 0. Here u^3 + a^2 = b^2*c. Notice that u must be odd.
All these observations lead to a (pseudo)code:
for u in range(1, n, 2)
a = (1 + 3u)/2
t = u^3 + a^2
find the largest b such that b^2 divides t
c = t / b^2
if a + b + c < n
they are a Cardano triplet
Your first problem, is the loop-in-loop-in-loop what will take 1.000.000.000 rounds for n=1000.
As you know already that n = a + b + c, you can take one loop out. the c-loop
and rewrite as:
for (long a = 0; a <= n; a++) {
for (long b = 0; b <= (n - a); b++) {
long c = n - a - b;
so you go from n * n * n -> n * n
If the equation is n => a + b + c (as in your problem statement), you can use:
for (long a = 0; a <= n; a++) {
for (long b = 0; b <= (n - a); b++) {
for (long c = 0; c <= (n - a - b); c++) {
Second, you are doing a format to a decimal and then convert back to double where as the Math.cbrt gives already a double. I would suggest not doing so.
The problem of "missing 19 triplets" is related to the point above. You only accept 1.0d as the correct answer, there in the previous step you did formatting on the doubles (most likely giving rounding issues). Even if you would take out the formatting, I believe it is better to allow for a bit more rounding error..
something like:
if (0.999 < addedVal && addedVal < 1.001)
However, I have no idea on the math of this equation as there must be a reason why you say there are 149 triplets.. Depending on the rounding for sure you have different answers... I believe there is something like mathemathical proof the triplets are 1.
Last what you can do: I believe the calculation of the Math.cbrt is not that fast. You are repeating this a lot. You can keep track of your calculation by placing the result of the Math,cbrt in a HashSet. The Key is the input and the Value the result of the Math.cbrt.
So first check if you have the Key already in the HashSet, if not calculate the cbrt and place it, if already available us it..
I have the following code:
public static void main(String[] args) {
int a = 3;
int b = 7;
int x = b; // x=b
int res = a; // res = a
int y = 1;
int invariant = 0;
System.out.println("a|b|x|y|res|invariant");
while (x > 0) {
if (x % 2 == 0) {
y = 2 * y;
x = x / 2;
} else {
res = res + y;
y = 2 * y;
x = (x - 1) / 2;
}
invariant = y + 2;
String output = String.format("%d|%d|%d|%d|%d|%d", a,b,x,y,res,invariant);
System.out.println(output);
}
// < res = a + b >
}
Which gives the following output:
a|b|x|y|res|invariant
3|7|3|2|4|4
3|7|1|4|6|6
3|7|0|8|10|10
However, if I change the numbers, the invariant isn't equal to the res anymore. Therefore my loop invariant for this problem is not correct.
I'm struggling really hard to find the correct loop invariant and would be glad if there's any hint that someone can give me.
My first impression after looking into the code and my results is that the loop invariant changes based on a and b. Let's say both a and b are odd numbers as they are in my example, then my Loop invariant is correct (at least it seems like it)
Is it correct to assume a loop variant like the following?
< res = y - 2 && a % 2 != 0 && b % 2 != 0 >
I did use different numbers and it seems like anytime I change them there's a different loop invariant and I struggle to find any pattern whatsoever.
I would really appreciate if someone can give me a hint or a general idea on how to solve this.
Thanks
This loop computes the sum a+b.
res is initialized to a.
Then, in each iteration of the loop, the next bit of the binary representation of b (starting with the least significant bit) is added to res, until the loop ends and res holds a+b.
How does it work:
x is initialized to b. In each iteration you eliminate the least significant bit. If that bit is 0, you simply divide x by 2. If it's 1, you subtract 1 and divide by 2 (actually it would be sufficient to divide by 2, since (x-1)/2==x/2 when x is an odd int). Only when you encounter a 1 bit, you have to add it (multiplied by the correct power of 2) to the result. y Holds the correct power of 2.
In your a=3, b=7 example, the binary representation of b is 111
In the first iteration, the value of res is a + 1 (binary) == a + 1 = 4
In the second iteration, the value of res is a + 11 (binary) == a + 3 = 6
In the last iteration, the value of res is a + 111 (binary) == a + 7 == 10
You could write the invariant as:
invariant = a + (b & (y - 1));
This takes advantage of the fact the at the end of the i'th iteration (i starting from 1), y holds 2^i, so y - 1 == 2^i - 1 is a number whose binary representation is i 1 bits (i.e. 11...11 with i bits). When you & this number with b, you get the i least significant bits of b.
I have this problem for the course "Algorithm and data structures"
You have a equation x^2+s(x)+200·x=N, where x and N are natural numbers and S(x) is the sum of digits of number x.
On the input we have N and A, B such that A≤B and A, B≤1,000,000,000. You need to check if there is a natural number x in the interval [A, B] that solves the equation. If found you need to return that number, otherwise return -1.
Example Input:
1456
10 80
Output
-1
I managed to solve this problem by using some math and a bit modified version of brute force algorithm. But are there any more effective(algorithm based) ways to solve this problem?
This is my code:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Range {
static int proveri(long N, long A, long B) {
long res = 0;
long start = (long)((-200 + Math.sqrt(4*N + 4))/2);
//System.out.println(start);
for (long i = Math.max(A, start); i <= B; i++) {
res = i * i + S(i) + 200 * i;
if(res == N)
return (int)i;
if(res > N)
return -1;
}
return -1;
}
static int S(long x) {
int sum = 0;
while(x > 0) {
sum += x % 10;
x /= 10;
}
return sum;
}
public static void main(String[] args) throws Exception {
int i,j,k;
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
long N = Long.parseLong(br.readLine());
StringTokenizer st = new StringTokenizer(br.readLine());
long A = Long.parseLong(st.nextToken());
long B = Long.parseLong(st.nextToken());
int res = proveri(N, A, B);
System.out.println(res);
br.close();
}
}
Here's a way where you can cut down on the amount of numbers you have to search.
Consider the equation anxn +
an-1xn-1 + ... + a1x + a0 = 0.
The rational root theorem states that if x = p/q is a solution,
then p divides a0 and q divides an
In your case, an is 1 and a0 is equal to S(x)-N. Thus, we know that any solution must divide S(x)-N.
This is where ben75's tip comes in. Since S(x) can't be bigger than 81, we can loop through all of the possible values of S(x), and solve separately. Something like this:
for each possible value of S(x)
loop through every factor x of S(x) - N
check if it is between A and B, if its digits sum to S(x)
and if it is a solution to x*x + 200x + S(x) = N.
if it is, return it.
return -1
There's also a pretty slick way for you to loop through all of the factors of a number, but I'll let you work that one out for yourself since this is for a course. My hint there is to look at the prime factorization of a number.
For the equation x^2+s(x)+200·x=N, consider
x^2 + 200·x + (N - s(x)) = 0
For a solution to a*x^2 + b*x + c = 0 equation with integer solutions, we need to have:
b^2 - 4*a*c >= 0 and must be a perfect square
Hence 200^2 - 4 * (N - s(x)) >=0 and a square or
10000 >= (N - s(x)) and (10,000 - (N - s(x)) must be a square. The square value is therefore less than 10,000 and hence there can be at most 100 values you need to check. With proper values of N it can be much lesser.
Also note that since N < 10,000, s(x) can be at most 36. These should cut down the range quite a bit.
Could anyone explain to me why the algorithm below is an error-free integer factorization method that always return a non-trivial factor of N.
I know how weird this sounds, but I designed this method 2 years ago and still don't understand the mathematical logic behind it, which is making it difficult for me to improve it. It's so simple that it involves only addition and subtraction.
public static long factorX( long N )
{
long x=0, y=0;
long b = (long)(Math.sqrt(N));
long a = b*(b+1)-N;
if( a==b ) return a;
while ( a!= 0 )
{
a-= ( 2+2*x++ - y);
if( a<0 ) { a+= (x+b+1); y++; }
}
return ( x+b+1 );
}
It seems that the above method actually finds a solution by iteration to the diophantine equation:
f(x,y) = a - x(x+1) + (x+b+1)y
where b = floor( sqrt(N) ) and a = b(b+1) - N
that is, when a = 0, f(x,y) = 0 and (x+b+1) is a factor of N.
Example: N = 8509
b = 92, a = 47
f(34,9) = 47 - 34(34+1) + 9(34+92+1) = 0
and so x+b+1 = 127 is a factor of N.
Rewriting the method:
public static long factorX(long N)
{
long x=1, y=0, f=1;
long b = (long)(Math.sqrt(N));
long a = b*(b+1)-N;
if( a==b ) return a;
while( f != 0 )
{
f = a - x*(x+1) + (x+b+1)*y;
if( f < 0 ) y++;
x++;
}
return x+b+1;
}
I'd really appreciate any suggestions on how to improve this method.
Here's a list of 10 18-digit random semiprimes:
349752871155505651 = 666524689 x 524741059 in 322 ms
259160452058194903 = 598230151 x 433211953 in 404 ms
339850094323758691 = 764567807 x 444499613 in 1037 ms
244246972999490723 = 606170657 x 402934339 in 560 ms
285622950750261931 = 576888113 x 495109787 in 174 ms
191975635567268981 = 463688299 x 414018719 in 101 ms
207216185150553571 = 628978741 x 329448631 in 1029 ms
224869951114090657 = 675730721 x 332780417 in 1165 ms
315886983148626037 = 590221057 x 535201141 in 110 ms
810807767237895131 = 957028363 x 847213937 in 226 ms
469066333624309021 = 863917189 x 542952889 in 914 ms
OK, I used Matlab to see what was going here. Here is the result for N=100000:
You are increasing x on each iteration, and the funny pattern of a variable is strongly related with the remainder N % x+b+1 (as you can see in the gray line of the plot, a + (N % (x+b+1)) - x = floor(sqrt(N))).
Thus, I think you are just finding the first factor larger than sqrt(N) by simple iteration, but with a rather obscure criterion to decide it is really a factor :D
(Sorry for the half-answer... I have to leave, I will maybe continue later).
Here is the matlab code, just in case you want it to test by yourself:
clear all
close all
N = int64(100000);
histx = [];
histDiffA = [];
histy = [];
hista = [];
histMod = [];
histb = [];
x=int64(0);
y=int64(0);
b = int64(floor(sqrt(double(N))));
a = int64(b*(b+1)-N);
if( a==b )
factor = a;
else
while ( a ~= 0 )
a = a - ( 2+2*x - y);
histDiffA(end+1) = ( 2+2*x - y);
x = x+1;
if( a<0 )
a = a + (x+b+1);
y = y+1;
end
hista(end+1) = a;
histb(end+1) = b;
histx(end+1) = x;
histy(end+1) = y;
histMod(end+1) = mod(N,(x+b+1));
end
factor = x+b+1;
end
figure('Name', 'Values');
hold on
plot(hista,'-or')
plot(hista+histMod-histx,'--*', 'Color', [0.7 0.7 0.7])
plot(histb,'-ob')
plot(histx,'-*g')
plot(histy,'-*y')
legend({'a', 'a+mod(N,x+b+1)-x', 'b', 'x', 'y'}); % 'Input',
hold off
fprintf( 'factor is %d \n', factor );
Your method is a variant of trial multiplication of (n-a)*(n+b), where n=floor(sqrt(N)) and b==1.
The algorithm then iterates a-- / b++ until the difference of the (n-a)*(n+b) - N == 0.
The partial differences (in respect of a and b) are in proportion to 2b and 2a respectively. Thus no true multiplication are necessary.
The complexity is a linear function of |a| or |b| -- the more "square" N is, the faster the method converges. In summary, there are much faster methods, one of the easiest to understand being the quadratic residue sieve.
Pardon my c#, I don't know Java.
Stepping x and y by 2 increases algorithm speed.
using System.Numerics; // needed for BigInteger
/* Methods ************************************************************/
private static BigInteger sfactor(BigInteger k) // factor odd integers
{
BigInteger x, y;
int flag;
x = y = iSqrt(k); // Integer Square Root
if (x % 2 == 0) { x -= 1; y += 1; } // if even make x & y odd
do
{
flag = BigInteger.Compare((x*y), k);
if (flag > 0) x -= 2;
y += 2;
} while(flag != 0);
return x; // return x
} // end of sfactor()
// Finds the integer square root of a positive number
private static BigInteger iSqrt(BigInteger num)
{
if (0 == num) { return 0; } // Avoid zero divide
BigInteger n = (num / 2) + 1; // Initial estimate, never low
BigInteger n1 = (n + (num / n)) >> 1; // right shift to divide by 2
while (n1 < n)
{
n = n1;
n1 = (n + (num / n)) >> 1; // right shift to divide by 2
}
return n;
} // end iSqrt()