【筆記】Binary Euclidean Algorithm
阿新 • • 發佈:2018-11-10
歐幾里得演算法
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; }