代码引用
cpp
int is_prime(int num) {
if (num <= 1) return 0;
if (num == 2 || num == 3) return 1;
if (num % 2 == 0 || num % 3 == 0) return 0;
for (int i = 5; i * i <= num; i += 6) {
if (num % i == 0 || num % (i + 2) == 0) return 0;
}
return 1;
}
一、数学原理
所有大于3的素数都可以写成 6k ± 1
(除2和3外所有素数都在6的邻域内)
为什么呢?因为所有整数都可以表示为6k、6k+1、6k+2、6k+3、6k+4、6k+5。其中,6k、6k+2、6k+4都是偶数,已经被num%2排除了。6k+3则是3的倍数,已经被num%3排除了。剩下的只有6k+1和6k+5(也就是6k-1)。
二、优化原理
1. 先排除特殊情况
cpp
if (num <= 1) return 0; // 1以下的数不是素数
if (num == 2 || num == 3) return 1; // 2和3是素数
if (num % 2 == 0 || num % 3 == 0) return 0; // 能被2或3整除的,肯定不是素数
- 这些判断快速排除一些明显不是素数的情况,尤其是偶数和能被3整除的数,避免后续多余的计算。
2. 只检查到平方根
cpp
for (int i = 5; i * i <= num; i += 6)
- 只需要检查到
sqrt(num)
,因为一个数如果有因子大于sqrt()
,对应的另一个因子必小于sqrt()
。
3. 以6的倍数间隔进行遍历
-
这是优化的关键:所有素数(除了2和3)都可以写成形式为
6k ± 1
的数(其中k为整数)。 -
这段代码只检查形如6k-1(即i)和6k+1(即i+2)的数是否能整除
num
。
简单总结:
这个算法利用了素数的数学性质(除2和3外所有素数都在6的邻域内),通过跳过非潜在因子(非6k±1的数),在保留正确性和完整性的基础上,大大优化了判断速度。