求最大公约数

来源:互联网 发布:记忆碎片剧情解析知乎 编辑:程序博客网 时间:2024/04/26 12:37

欧几里德:辗转相除的办法。   

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 100int 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 countchen@chen-book1:~$ ./count2 s 536068 us1 s 920305 us26 s 448318 us24 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 2000int 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位以上的整数啊。