欧几里德:辗转相除的办法。
Stein:奇数偶数分开考虑,没有除法,只有移位,加减。
#include <stdio.h> #include <sys/time.h> int gcd1(int a, int b) { while (1) { a = a % b; if (a == 0) return b; b = b % a; if (b == 0) return a; } } int gcd0(int M, int N) { int Rem; while (N > 0) { Rem = M % N; M = N; N = Rem; } return M; } int gcd2(int a, int b) { if (a < b) { a ^= b; b ^= a; a ^= b; } if (b == 0) return a; if ((a & 1) == 0 && (b & 1) == 0) return 2 * gcd2(a >> 1, b >> 1); else if ((a & 1) == 0) return gcd2(a >> 1, b); else if ((b & 1) == 0) return gcd2(a, b >> 1); else return gcd2((a - b) >> 1, b); } int gcd3(int a, int b) { if (a < b) { //arrange so that a>b int temp = a; a = b; b = temp; } if (0 == b) //the base case return a; if (a % 2 == 0 && b % 2 == 0) //a and b are even return 2 * gcd3(a / 2, b / 2); if (a % 2 == 0) // only a is even return gcd3(a / 2, b); if (b % 2 == 0) // only b is even return gcd3(a, b / 2); return gcd3((a - b) / 2, b); // a and b are odd } #define C 100000 #define D 100 int main() { struct timeval starttime, endtime; // gcd0 gettimeofday(&starttime, 0); { int c; c = C; int d = D; int i; int g; while (--c) { for (i = d; i < 10 * d; i++) { g = gcd0(i, i + 1); } } } gettimeofday(&endtime, 0); if (endtime.tv_usec < starttime.tv_usec) { endtime.tv_sec--; endtime.tv_usec += 1000000; } printf("%ld s %ld us\n", endtime.tv_sec - starttime.tv_sec, endtime.tv_usec - starttime.tv_usec); /////////////////// gcd1 gettimeofday(&starttime, 0); { int c; c = C; int d = D; int i; int g; while (--c) { for (i = d; i < 10 * d; i++) { g = gcd1(i, i + 1); } } } gettimeofday(&endtime, 0); if (endtime.tv_usec < starttime.tv_usec) { endtime.tv_sec--; endtime.tv_usec += 1000000; } printf("%ld s %ld us\n", endtime.tv_sec - starttime.tv_sec, endtime.tv_usec - starttime.tv_usec); /// gcd 2 gettimeofday(&starttime, 0); { int c; c = C; int d = D; int i; int g; while (--c) { for (i = d; i < 10 * d; i++) { g = gcd2(i, i + 1); } } } gettimeofday(&endtime, 0); if (endtime.tv_usec < starttime.tv_usec) { endtime.tv_sec--; endtime.tv_usec += 1000000; } printf("%ld s %ld us\n", endtime.tv_sec - starttime.tv_sec, endtime.tv_usec - starttime.tv_usec); //gcd 3 gettimeofday(&starttime, 0); { int c; c = C; int d = D; int i; int g; while (--c) { for (i = d; i < 10 * d; i++) { g = gcd3(i, i + 1); } } } gettimeofday(&endtime, 0); if (endtime.tv_usec < starttime.tv_usec) { endtime.tv_sec--; endtime.tv_usec += 1000000; } printf("%ld s %ld us\n", endtime.tv_sec - starttime.tv_sec, endtime.tv_usec - starttime.tv_usec); return 0; }运行:
chen@chen-book1:~$ gcc count.c -o count chen@chen-book1:~$ ./count 2 s 536068 us 1 s 920305 us 26 s 448318 us 24 s 646252 us
#define C 100
#define D 100000
则:
chen@chen-book1:~$ ./count
2 s 482367 us
1 s 878122 us
55 s 522424 us
52 s 281608 us
chen@chen-book1:~$
换成cpp版的long long
#include <stdio.h> #include <sys/time.h> template <class T> T gcd1(T a, T b) { while (1) { a = a % b; if (a == 0) return b; b = b % a; if (b == 0) return a; } } template <class T> T gcd0(T a, T b) { int rem; while (b > 0) { rem = a % b; a = b; b = rem; } return a; } template <class T> T gcd2(T a, T b) { if (a < b) { a ^= b; b ^= a; a ^= b; } if (b == 0) return a; if ((a & 1) == 0 && (b & 1) == 0) return 2 * gcd2(a >> 1, b >> 1); else if ((a & 1) == 0) return gcd2(a >> 1, b); else if ((b & 1) == 0) return gcd2(a, b >> 1); else return gcd2((a - b) >> 1, b); } template <class T> T gcd3(T a, T b) { if (a < b) { //arrange so that a>b T temp = a; a = b; b = temp; } if (0 == b) //the base case return a; if (a % 2 == 0 && b % 2 == 0) //a and b are even return 2 * gcd3(a / 2, b / 2); if (a % 2 == 0) // only a is even return gcd3(a / 2, b); if (b % 2 == 0) // only b is even return gcd3(a, b / 2); return gcd3((a - b) / 2, b); // a and b are odd } #define C 2 #define D 10000*10000*10000LL #define N 2000 int main() { struct timeval starttime, endtime; // gcd0 gettimeofday(&starttime, 0); { int c; c = C; long long d = D; long long i; long long g; while (--c) { for (i = d; i < d+N; i++) { g = gcd0(i, i + 1); } } } gettimeofday(&endtime, 0); if (endtime.tv_usec < starttime.tv_usec) { endtime.tv_sec--; endtime.tv_usec += 1000000; } printf("%ld s %ld us\n", endtime.tv_sec - starttime.tv_sec, endtime.tv_usec - starttime.tv_usec); /////////////////// gcd1 gettimeofday(&starttime, 0); { int c; c = C; long long d = D; long long i; long long g; while (--c) { for (i = d; i < d+N; i++) { g = gcd1(i, i + 1); } } } gettimeofday(&endtime, 0); if (endtime.tv_usec < starttime.tv_usec) { endtime.tv_sec--; endtime.tv_usec += 1000000; } printf("%ld s %ld us\n", endtime.tv_sec - starttime.tv_sec, endtime.tv_usec - starttime.tv_usec); /// gcd 2 gettimeofday(&starttime, 0); { int c; c = C; long long d = D; long long i; long long g; while (--c) { for (i = d; i < N + d; i++) { g = gcd2(i, i + 1); } } } gettimeofday(&endtime, 0); if (endtime.tv_usec < starttime.tv_usec) { endtime.tv_sec--; endtime.tv_usec += 1000000; } printf("%ld s %ld us\n", endtime.tv_sec - starttime.tv_sec, endtime.tv_usec - starttime.tv_usec); //gcd 3 gettimeofday(&starttime, 0); { int c; c = C; long long d = D; long long i; long long g; while (--c) { for (i = d; i < N + d; i++) { g = gcd3(i, i + 1); } } } gettimeofday(&endtime, 0); if (endtime.tv_usec < starttime.tv_usec) { endtime.tv_sec--; endtime.tv_usec += 1000000; } printf("%ld s %ld us\n", endtime.tv_sec - starttime.tv_sec, endtime.tv_usec - starttime.tv_usec); return 0; }
chen@chen-book1:~$ g++ count.cpp -o count
chen@chen-book1:~$ ./count
0 s 109 us
0 s 188 us
0 s 3998 us
0 s 4206 us
还是这样。。。。第二种Stein还比不上第一种呢。但是我找不到128位以上的整数啊。