找到C系统中可表示为整数的最大数字对,其最大公约数为1

时间:2017-06-13 12:54:57

标签: c greatest-common-divisor

我想找到可以表示为GCD为1的整数的最大数字对,以下是我的代码,但它太慢而且可能很愚蠢。你有更好的主意吗?如何实现呢?

#include <stdio.h>    

int gcd(int u, int v)
{
    while (u > 0) {
        if (u < v) {
            int t = u;
            u = v;
            v = t;
        }
        u = u - v;
    }
    return v;
}    

int main()
{
    int u, v;
    u = v = ~(1 << (sizeof(int) * 8 - 1));    

    while (u > 0) {
        if (gcd(u, v) == 1) {
            printf("%d %d\n", u, v);
            break;
        }
        --u;
    }
}

1 个答案:

答案 0 :(得分:2)

您的代码存在多个问题:

  • 您使用的是int类型,但可能会有更大的整数类型可以产生更大的对:unsigned intunsigned longunsigned long long ...问题规范必须更加精确。

  • 表达式~(1 << (sizeof(int) * 8 - 1))导致未定义的行为,因为中间值1 << (sizeof(int) * 8 - 1)导致算术溢出。另请注意,某些稀有系统上的字节可能超过8位。使用INT_MAX中定义的<limits.h>可获得更好的便携性。

  • 您没有枚举所有值对:在32位系统上,您会找到最大的int对,但对于INT_MAX与2147483647不同的另一个系统,您可能会错过最大金额的那对。

  • gcd()函数,原始的欧几里德方法,效率非常低。您应该使用基于模数的版本,例如:

    int gcd(int a, int b) {
        while (b != 0) {
            int t = b;
            b = a % b;
            a = t;
        }
        return a;
    }
    
  • 最后,很明显,对于大于n0的任何整数gcd(n, n + 1) == gcd(n, 1) == 1。因此,您的问题很简单,解决方案是最大的整数及其前身。

    因此最大的便携式对是:

    #include <limits.h>
    #include <stdio.h>
    
    int main(void) {
        printf("%llu %llu\n", ULLONG_MAX, ULLONG_MAX - 1);
        return 0;
    }