Euclidean greatest common divisor for more than two numbers

前端 未结 6 1336
谎友^
谎友^ 2020-12-16 14:48

Can someone give an example for finding greatest common divisor algorithm for more than two numbers?

I believe programming language doesn\'t matter.

相关标签:
6条回答
  • 2020-12-16 15:26

    I just updated a Wiki page on this.

    [https://en.wikipedia.org/wiki/Binary_GCD_algorithm#C.2B.2B_template_class]

    This takes an arbitrary number of terms. use GCD(5, 2, 30, 25, 90, 12);

    template<typename AType> AType GCD(int nargs, ...)
    {
        va_list arglist;
        va_start(arglist, nargs);
    
        AType *terms = new AType[nargs];
    
        // put values into an array
        for (int i = 0; i < nargs; i++) 
        {
            terms[i] = va_arg(arglist, AType);
            if (terms[i] < 0)
            {
                va_end(arglist);
                return (AType)0;
            }
        }
        va_end(arglist);
    
        int shift = 0;
        int numEven = 0;
        int numOdd = 0;
        int smallindex = -1;
    
        do
        {
            numEven = 0;
            numOdd = 0;
            smallindex = -1;
    
            // count number of even and odd
            for (int i = 0; i < nargs; i++)
            {
                if (terms[i] == 0)
                    continue;
    
                if (terms[i] & 1)
                    numOdd++;
                else
                    numEven++;
    
                if ((smallindex < 0) || terms[i] < terms[smallindex])
                {
                    smallindex = i;
                }
            }
    
            // check for exit
            if (numEven + numOdd == 1)
                continue;
    
            // If everything in S is even, divide everything in S by 2, and then multiply the final answer by 2 at the end.
            if (numOdd == 0)
            {
                shift++;
                for (int i = 0; i < nargs; i++)
                {
                    if (terms[i] == 0)
                        continue;
    
                    terms[i] >>= 1;
                }
            }
    
            // If some numbers in S  are even and some are odd, divide all the even numbers by 2.
            if (numEven > 0 && numOdd > 0)
            {
                for (int i = 0; i < nargs; i++)
                {
                    if (terms[i] == 0)
                        continue;
    
                    if ((terms[i] & 1)  == 0) 
                        terms[i] >>= 1;
                }
            }
    
            //If every number in S is odd, then choose an arbitrary element of S and call it k.
            //Replace every other element, say n, with | n−k | / 2.
            if (numEven == 0)
            {
                for (int i = 0; i < nargs; i++)
                {
                    if (i == smallindex || terms[i] == 0)
                        continue;
    
                    terms[i] = abs(terms[i] - terms[smallindex]) >> 1;
                }
            }
    
        } while (numEven + numOdd > 1);
    
        // only one remaining element multiply the final answer by 2s at the end.
        for (int i = 0; i < nargs; i++)
        {
            if (terms[i] == 0)
                continue;
    
            return terms[i] << shift;
        }
        return 0;
    };
    
    0 讨论(0)
  • 2020-12-16 15:27

    A little late to the party I know, but a simple JavaScript implementation, utilising Sam Harwell's description of the algorithm:

    function euclideanAlgorithm(a, b) {
        if(b === 0) {
            return a;
        }
        const remainder = a % b;
        return euclideanAlgorithm(b, remainder)
    }
    
    function gcdMultipleNumbers(...args) { //ES6 used here, change as appropriate
      const gcd = args.reduce((memo, next) => {
          return euclideanAlgorithm(memo, next)}
      );
    
      return gcd;
    }
    
    gcdMultipleNumbers(48,16,24,96) //8
    
    0 讨论(0)
  • 2020-12-16 15:33

    For golang, using remainder

    func GetGCD(a, b int) int {
        for b != 0 {
            a, b = b, a%b
        }
        return a
    }
    func GetGCDFromList(numbers []int) int {
        var gdc = numbers[0]
        for i := 1; i < len(numbers); i++ {
            number := numbers[i]
            gdc  = GetGCD(gdc, number)
        }
        return gdc
    }
    
    0 讨论(0)
  • 2020-12-16 15:44

    The GCD of 3 numbers can be computed as gcd(a, b, c) = gcd(gcd(a, b), c). You can apply the Euclidean algorithm, the extended Euclidian or the binary GCD algorithm iteratively and get your answer. I'm not aware of any other (smarter?) ways to find a GCD, unfortunately.

    0 讨论(0)
  • 2020-12-16 15:47

    Start with the first pair and get their GCD, then take the GCD of that result and the next number. The obvious optimization is you can stop if the running GCD ever reaches 1. I'm watching this one to see if there are any other optimizations. :)

    Oh, and this can be easily parallelized since the operations are commutative/associative.

    0 讨论(0)
  • 2020-12-16 15:50

    In Java (not optimal):

    public static int GCD(int[] a){
        int j = 0;
    
        boolean b=true;
        for (int i = 1; i < a.length; i++) {
            if(a[i]!=a[i-1]){
                b=false;
                break;
            }
        }
        if(b)return a[0];
        j=LeastNonZero(a);
        System.out.println(j);
        for (int i = 0; i < a.length; i++) {
            if(a[i]!=j)a[i]=a[i]-j;
        }
        System.out.println(Arrays.toString(a));
        return GCD(a);
    }
    
    public static int LeastNonZero(int[] a){
        int b = 0;
        for (int i : a) {
            if(i!=0){
                if(b==0||i<b)b=i;
            }
        }
        return b;
    }
    
    0 讨论(0)
提交回复
热议问题