📜  C程序查找数的最大素数(1)

📅  最后修改于: 2023-12-03 15:14:26.439000             🧑  作者: Mango

C程序查找数的最大素数

素数即质数,指除1和它本身之外没有其他因数的正整数。而找到一个数的最大素数是一个常见的问题,本文将介绍如何在C程序中实现这个问题的解答。

算法简介

常规的找素数的方法是从2开始,一直到该数的平方根止,用这个数去除以每个数,如果都不能整除,则该数为素数。但这种方法对于较大的数来说效率较低,因此我们需要运用更高效的算法。

一种常见的高效的素数判断算法是埃拉托色尼筛法(Sieve of Eratosthenes),该算法通过排除不是素数的数来筛选出素数。具体实现可以参考以下几个步骤:

  1. 生成2到n之间的所有整数;
  2. 将2作为素数,将能被2整除的数排除掉;
  3. 将下一个素数3筛选出来,然后将能被3整除的数排除掉;
  4. 重复上一步操作,筛选出4,将能被4整除的数排除掉,直到不能再筛选出新的素数为止,此时剩下的所有数均为素数。

但是,这个算法并不能直接解决本题求一个给定数的最大素数的问题。因此,我们将采用另一个高效的判断素数的算法——Miller-Rabin算法。

Miller-Rabin算法通过随机选择一定次数的基数,进行一定次数的模幂运算,来判断一个数是否为素数。如果某次模幂运算失败,则该数为合数;如果所有模幂运算都成功,则该数为素数。

代码实现

为了方便阅读和理解,我们将代码分为以下几个模块:

  • 判断素数的函数:millerRabin()
  • 查找最大素数的函数:findMaxPrime()
  • 主函数:main()
判断素数的函数
int millerRabin(long long p, int t) {
    long long odd = p - 1;

    // 计算s和d
    int s = 0;
    while (odd % 2 == 0) {
        odd /= 2;
        s++;
    }
    long long d = odd;

    // 进行t次测试
    srand((unsigned)time(NULL));
    for (int i = 0; i < t; i++) {
        long long randNum = rand() % (p - 2) + 2;
        long long x = powMod(randNum, d, p);
        if (x == 1 || x == p - 1) continue;

        int flag = 0;
        for (int j = 1; j < s; j++) {
            x = powMod(x, 2, p);
            if (x == p - 1) {
                flag = 1;
                break;
            }
        }
        if (flag == 0) return 0;
    }

    return 1;
}

该函数使用了一个参数t,表示进行的测试次数,t值越高,判断的准确率也越高。但同时,t值过高也会导致整个程序的效率下降。

对于每次测试,该函数使用了随机生成的数randNum和计算出的d,计算 $randNum^d$ 的模p幂,然后作进一步的验证,确定该数是否为素数。

查找最大素数的函数
unsigned long long findMaxPrime(unsigned long long n) {
    if (n == 2 || n == 3) return n;
    if (n == 1 || n % 2 == 0) return 2;
    if (n == 3 || n == 5) return n;

    unsigned long long upper, lower;
    if (n % 6 == 5) {
        lower = n - 2;
        upper = n + 2;
    }
    else if (n % 6 == 1) {
        lower = n - 4;
        upper = n + 4;
    }

    for (unsigned long long p = upper; p >= lower; p -= 6) {
        if (millerRabin(p, 20)) return p;
        if (millerRabin(p - 4, 20)) return p - 4;
    }

    return 0;
}

该函数采用了一些优化方法,如根据n模6的余数确定最大素数所在的区间,然后对区间内的素数进行判断,最后返回找到的最大素数。

主函数
int main() {
    unsigned long long n;
    printf("Please input a positive integer: ");
    scanf("%llu", &n);

    unsigned long long maxPrime = findMaxPrime(n);
    printf("The maximum prime number is %llu.\n", maxPrime);

    return 0;
}

该函数读取用户输入的数n,并调用findMaxPrime()函数查找n的最大素数,最后输出结果。

总结

本文介绍了两种判断素数的高效算法:埃拉托色尼筛法和Miller-Rabin算法,以及如何在C程序中使用Miller-Rabin算法查找一个数的最大素数。在实际应用中,需要根据具体情况选择合适的算法和参数,以保证判断的准确性和效率。