【笔记】Binary Euclidean Algorithm

欧几里得算法

u,v都是偶数时 gcd(u, v) = 2gcd(u/2, v/2)

u,v只有一个偶数时,偶数u时  gcd(u, v) = gcd(u/2, v);偶数v时 gcd(u, v) = gcd(u, v/2)

u,v都是奇数时,u > v时 gcd(u, v) = gcd((u - v)/2, v); u < v时 gcd(u, v) = gcd(u, (v - u)/2)

Unsigned版本

/// <summary>
/// 计算<paramref name="a"/>和<paramref name="b"/>的最大公约数
/// </summary>
public static uint GreatestCommonDivisor(uint a, uint b)
{
    if (a == 0) return b;
    if (b == 0) return a;

    var aZeros = a.NumberOfTrailingZeros();
    var bZeros = b.NumberOfTrailingZeros();
    a >>= aZeros;
    b >>= bZeros;

    var t = Math.Min(aZeros, bZeros);

    while (a != b)
    {
        if (a > b)
        {
            a -= b;
            a >>= a.NumberOfTrailingZeros();
        }
        else
        {
            b -= a;
            b >>= b.NumberOfTrailingZeros();
        }
    }

    return a << t;
}

NumberOfTrailingZeros用来计算二进制尾数0的个数

/// <summary>
/// <paramref name="n"/>二进制尾数0的个数
/// </summary>
public static int NumberOfTrailingZeros(this uint n)
{
    if (n == 0) return 32;

    var c = 31;
    var t = n << 16; if (t != 0u) { c -= 16; n = t; }
    t = n << 8; if (t != 0u) { c -= 8; n = t; }
    t = n << 4; if (t != 0u) { c -= 4; n = t; }
    t = n << 2; if (t != 0u) { c -= 2; n = t; }
    t = n << 1; if (t != 0u) { c -= 1; }

    return c;
}

Signed版本

/// <summary>
/// 计算<paramref name="a"/>和<paramref name="b"/>的最大公约数
/// </summary>
public static int GreatestCommonDivisor(int a, int b)
{
    if (a == 0) return b;
    if (b == 0) return a;

    a = (a ^ (a >> 31)) - (a >> 31);//a = abs(a)
    b = (b ^ (b >> 31)) - (b >> 31);//b = abs(b)

    var aZeros = a.NumberOfTrailingZeros();
    var bZeros = b.NumberOfTrailingZeros();
    a >>= a.NumberOfTrailingZeros();
    b >>= b.NumberOfTrailingZeros();

    var t = Math.Min(aZeros, bZeros);

    while (a != b)
    {
        if (a > b)
        {
            a -= b;
            a >>= a.NumberOfTrailingZeros();
        }
        else
        {
            b -= a;
            b >>= b.NumberOfTrailingZeros();
        }
    }

    return a << t;
}


/// <summary>
/// <paramref name="n"/>二进制尾数0的个数
/// </summary>
public static int NumberOfTrailingZeros(this int n)
{
    if (n == 0) return 32;

    var c = 31;
    var t = n << 16; if (t != 0) { c -= 16; n = t; }
    t = n << 8; if (t != 0) { c -= 8; n = t; }
    t = n << 4; if (t != 0) { c -= 4; n = t; }
    t = n << 2; if (t != 0) { c -= 2; n = t; }
    t = n << 1; if (t != 0) { c -= 1; }

    return c;
}

猜你喜欢

转载自blog.csdn.net/xueyan0096/article/details/83653254