Returns the greatest common divisor of two positive numbers (this precondition is not checked and the result is undefined if not fulfilled) using the "binary gcd" method which avoids division and modulo operations. - Java java.lang

Java examples for java.lang:Math Number

Description

Returns the greatest common divisor of two positive numbers (this precondition is not checked and the result is undefined if not fulfilled) using the "binary gcd" method which avoids division and modulo operations.

Demo Code

/*******************************************************************************
 * Copyright 2014 See AUTHORS file.//from  w  w w.ja v  a  2  s  . c o m
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ******************************************************************************/
//package com.java2s;

public class Main {
    public static void main(String[] argv) throws Exception {
        int args = 2;
        System.out.println(gcdPositive(args));
    }

    /** Returns the greatest common divisor of two <em>positive</em> numbers (this precondition is <em>not</em> checked and the
     * result is undefined if not fulfilled) using the "binary gcd" method which avoids division and modulo operations. See Knuth
     * 4.5.2 algorithm B. The algorithm is due to Josef Stein (1961).
     * <p>
     * Special cases:
     * <ul>
     * <li>The result of {@code gcd(x, x)}, {@code gcd(0, x)} and {@code gcd(x, 0)} is the value of {@code x}.</li>
     * <li>The invocation {@code gcd(0, 0)} is the only one which returns {@code 0}.</li>
     * </ul>
     * 
     * @param a a non negative number.
     * @param b a non negative number.
     * @return the greatest common divisor. */
    public static int gcdPositive(int a, int b) {
        if (a == 0)
            return b;

        if (b == 0)
            return a;

        // Make "a" and "b" odd, keeping track of common power of 2.
        final int aTwos = Integer.numberOfTrailingZeros(a);
        a >>= aTwos;
        final int bTwos = Integer.numberOfTrailingZeros(b);
        b >>= bTwos;
        final int shift = aTwos <= bTwos ? aTwos : bTwos; // min(aTwos, bTwos);

        // "a" and "b" are positive.
        // If a > b then "gdc(a, b)" is equal to "gcd(a - b, b)".
        // If a < b then "gcd(a, b)" is equal to "gcd(b - a, a)".
        // Hence, in the successive iterations:
        // "a" becomes the absolute difference of the current values,
        // "b" becomes the minimum of the current values.
        while (a != b) {
            final int delta = a - b;
            b = a <= b ? a : b; // min(a, b);
            a = delta < 0 ? -delta : delta; // abs(delta);

            // Remove any power of 2 in "a" ("b" is guaranteed to be odd).
            a >>= Integer.numberOfTrailingZeros(a);
        }

        // Recover the common power of 2.
        return a << shift;
    }

    /** Returns the greatest common divisor of the given absolute values. This implementation uses {@link #gcdPositive(int, int)}
     * and has the same special cases.
     * 
     * @param args non-negative numbers
     * @return the greatest common divisor. */
    public static int gcdPositive(int... args) {
        if (args == null || args.length < 2)
            throw new IllegalArgumentException(
                    "gcdPositive requires at least two arguments");
        int result = args[0];
        int n = args.length;
        for (int i = 1; i < n; i++) {
            result = gcdPositive(result, args[i]);
        }
        return result;
    }
}

Related Tutorials