判定素数的3种方法-枚举法、筛素数法、六素数法

本文介绍了三种判定素数的方法:枚举法、筛素数法和六素数法。枚举法通过判断一个数是否能被其他数整除来确定其是否为素数,筛素数法通过筛选出所有素数,减少后续判断次数,优化了时间复杂度。六素数法则进一步优化了枚举法,只考虑6的倍数加1或5的形式,提高效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

判定素数的3种方法-枚举法、筛素数法、六素数法

素数的定义

一个大于 1 的自然数,除了 1 和 它自身外,不能被其他自然数整除的数叫做质数;否则称合数(规定 1 即不是质数也不是合数)

枚举法

思路

我们可以根据素数的定义一步步写出函数判断一个数是否是素数

1)一个大于 1 的自然数

static boolean isPrime(int num) {
   	// 根据素数定义可知素数为大于 1 的自然数
    if (num < 2) return false;
    //...
}

2)除了 1 和 它自身外,不能被其他自然数整除的数叫做质数

static boolean isPrime(int num) {
    // 根据素数定义可知素数为大于 1 的自然数
    if (num < 2) return false;

    for (int i = 2; i < num; i++) {
        // 若除了 1 和 它自身外,num 能被 i 整除,则为合数,返回 false
        if (num % i == 0)
            return false;
    }
    // 找不到除了 1 和 它自身外,能被其他自然数整除的数,返回 true
    return true;
}

上面这个函数已经可以判断一个 int 类型的数是否为素数了。

根据数学知识我们可以判断出 i i i 的最大值取到 sqrt(num)

优化后

static boolean isPrime(int num) {
    if (num < 2) return false;
	int k = (int) Math.sqrt(num) + 1;
    for (int i = 2; i < k; i++) {
        if (num % i == 0)
            return false;
    }
    return true;
}

优化后的函数将时间复杂度从 O ( n ) O(n) O(n) 降到 O ( n ) O(\sqrt{n}) O(n )

筛素数法

如果我们需要频繁的判断一些数是否为素数,使用筛素数法可以节约极大量的时间。

(定所求的最大值为 n n n m m m 为小于等于 n n n 的素数个数,则枚举法所需的时间为 O ( n 2 ) O(n^2) O(n2),而筛素数法所需要的时间为 O ( m ∗ n ) O(m*n) O(mn)

思路

如果 i i i 为素数,则 2 ∗ i , 3 ∗ i , 4 ∗ i , . . . . 2 * i, 3 * i, 4* i,.... 2i,3i,4i,.... 这些数一定不为素数

根据这个思路,如过 i i i 是素数,我们则将 2 ∗ i , 3 ∗ i , 4 ∗ i , . . . . 2 * i, 3 * i, 4* i,.... 2i,3i,4i,.... 标记为合数

演示

第 1 轮筛选

截屏2021-04-14 14.25.00

第 2 轮筛选

截屏2021-04-14 14.27.45

第 3 轮筛选

截屏2021-04-14 14.29.05

第 k 轮筛选

截屏2021-04-14 14.34.40

代码

static boolean isPrime[MAX_N]
static void f() {
    Arrays.fill(isPrime, true);
    isPrime[0] = isPrime[1] = false;
    for (int i = 2; i < MAX_N; i++) {
        if (isPrime[i]) {
            for (int j = 2; j * i < MAX_N; j++) {
                isPrime[j * i] = false; 
            }
        }
    }
}

六素数法

筛素数法已经非常高效了,可是若我们需要判断的 n u m num num 值远远大于 1 1 1,则我们浪费了许多不必要的内存开销,甚至 n u m num num 太大时,以至于无法开到这么大的数组。由此我们引入六素数法判断,此法极大的提高了优化后的枚举法。

思路

对于大于等于 5 5 5 的数,我们可以用 6 n , 6 n + 1 , 6 n + 2 , 6 n + 3 , 6 n + 4 , 6 n + 5 6n,6n+1,6n+2,6n+3,6n+4,6n+5 6n,6n+1,6n+2,6n+3,6n+4,6n+5 表示

6 6 6 的真因子有 1 、 2 、 3 1、2、3 123 ,则有

6 n 6n 6n 可以被 2 、 3 2、3 23 整除

6 n + 2 , 6 n + 4 6n+2, 6n+4 6n+2,6n+4 可以被 2 2 2 整除

6 n + 3 6n+3 6n+3 可以被 3 3 3 整除

则对于大于等于 5 5 5 的数,若其为素数则一定满足 6 n + 1 6n + 1 6n+1 6 n + 5 6n+5 6n+5 的形式

代码

static boolean isPrime(int num) {
    if (num <= 3) return num > 1;
    if (num % 6 != 1 && num % 6 != 5) return false;
    int k = (int) Math.sqrt(num) + 1;
    for (int i = 5; i < k; i += 6) {
        if (num % i == 0 || num % (i + 2) == 0)
            return false;
    }
    return true;
}

i i i 每次加 6,相比较普通的枚举法,6 素数法极大的提高了效率

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值