Greatest common divisor is a very classical mathematical problem, for this problem there are four general solutions , mass factor decomposition method, short division, but more commonly used or the method of dividing, the algorithm from the Euclid's book "Geometry originally", there is a "nine chapters of Arithmetic," the more subtractive loss method, The general realization of the time is achieved by the division of the method, the basic logic is this: Assume that the greatest common divisor of a and B are represented as f (a, a, and a>=b>0). Now take k=a/b,m=a%b, then A=k*b+m, m=a-k*b;x and y can be divisible by f (A, B), then M can be divisible by f (A, B), F (A, B) = f (b,a%b).
Loop Value
Based on the above logic, we define two numbers, A, B, first mod=a%b the remainder, then assigns a value to B to a,mod, jumps out of the loop to return a is greatest common divisor, the code is as follows:
-(Nsinteger) Maxdivisor: (Nsinteger) a secondnumber: (nsinteger) b{ if (a<b) { a=a+b; B=a-b; a=a-b; } while (b!=0) { nsinteger mod=a%b; a=b; B=mod; } return A;}
A recursive version of the divide
For the understanding of loops, we can implement them recursively:
-(Nsinteger) Maxmodrecursive: (Nsinteger) a secondnumber: (nsinteger) b{ if (a<b) { a=a+b; B=a-b; a=a-b; } if (b==0) { return A; } else{ return [self maxmodrecursive:b secondnumber:a%b]; }
the deformation of the division
The method of dividing the greatest common divisor of large integers, the efficiency of the Division method has a bottleneck, for large integers, the cost of modulo operations (used to divide) is very expensive, this is the limitations of Euclid algorithm, in fact, we can learn from Euclid's Euclidean method of the divide to optimize. We need to realize that a mathematical knowledge is the number of conventions between a two-digit greatest common divisor equals a smaller number and two decimal-difference values. You can use the "-" operation, that is, F (A, B) =f (A-B,B).
-(Nsinteger) Maxrecursive: (Nsinteger) a secondnumber: (nsinteger) b{ if (a<b) { a=a+b; B=a-b; a=a-b; } if (b==0) { return A; } else{ return [self maxrecursive:b secondnumber:a-b]; }
For the large number of operations solved by the above form, that is, when a and b a lot of difference, the algorithm will be too many iterations, resulting in a low efficiency of the algorithm, a=1000,b=1, we have to consider other optimizations.
Shift Operations
The above method does not solve the problem of large integers and iterations well, we can solve the above problems by the shift operation:
(1) If b=k*b1,a=k*a1. Then there are f (A, B) =k*f (A1,B1)
(2) If A=p*a2,p is a prime number and b%p! = 0, then f (A, B) = f (p*a2,b) = f (a2,b)
So we get the following workaround:
Put P = 2,
If A and B are even, F (A, B) = 2*f (A/2,B/2) = 2*f (a>>1,b>>1);
If a is an even number, B is odd, f (A, B) = f (a/2,b) = f (a>>1,b);
If A is odd, B is even, F (A, B) = f (A,B/2) = f (a,b>>1);
2 (Max (A, b))
-(Nsinteger) Maxlogic: (Nsinteger) a secondnumber: (nsinteger) b{ if (a<b) { a=a+b; B=a-b; a=a-b; } if (b==0) { return A; } else{ //a is even if ((a&1) ==0) { //b is even if ((b&1) ==0) { return [self maxlogic:a>>1 secondnumber:b>>1]<<1; } Else{//b is an odd return [self maxlogic:a>>1 secondnumber:b];} else{//a is odd //b is even if ((b&1) ==0) { return [self maxlogic:a secondnumber:b>>1]; } Else{//b is an odd return [self maxlogic:b secondnumber:a-b] ; }} return 0;}
By shifting and subtraction, the large integer division is avoided, and the efficiency of the algorithm is improved, and some things still need to be researched frequently ~
Algorithm-Greatest common divisor