给出一个自然数表(1,2,…,n),要求尽可能快的找出其中的质数,应该怎么做?
有两种思路:一种是遍历,一个个找质数,一种是去掉所有的合数.那么选择哪一种呢?
不管怎样,先来看看如何判定质数或者合数.
质数和合数的判定
质数和合数的定义在这不多讲.为判断是质数还是合数,最经典的方案就是遍历小于该数的所有整数(除了1),如果出现整除,那就不是.
就像这样:
while(i=2;i<N;i++)
{
if(N%i==0)
{
return FALSE;
}
}
return TRUE;
但这样需要扫描N-1次,对于大数而言要花相当多的时间,显然不是优解.那么在这里引入一个定理:
t
h
e
o
r
e
m
:
∀
x
∈
z
且
x
是
合
数
∃
1
≤
a
≤
x
使
得
a
∣
x
{theorem: }\\ \forall x\in\mathbb{z}且\ x是合数\\ \exists 1\le a\leq \sqrt{x} \\使得 a|x
theorem:∀x∈z且 x是合数∃1≤a≤x使得a∣x
对该定理用反证法证明:
p
r
o
o
f
:
f
o
r
合
数
x
,
∃
整
数
对
(
a
,
b
)
,
a
b
˙
=
x
.
(
a
!
=
0
a
n
d
b
!
=
0
)
i
f
a
<
x
a
n
d
b
<
x
→
a
b
˙
<
x
∴
原
假
设
不
成
立
.
Q
.
E
.
D
{proof:}\\ for 合数x,\\ \exists 整数对(a,b),a\dot b=x.(a!=0 and b!=0)\\ if a< \sqrt{x}\ and\ b< \sqrt{x}\\ \rightarrow a\dot b < x\\ \therefore 原假设不成立.\\ Q.E.D
proof:for合数x,∃整数对(a,b),ab˙=x.(a!=0andb!=0)ifa<x and b<x→ab˙<x∴原假设不成立.Q.E.D
所以现在提出第一个改进:
只用扫描到
x
\sqrt{x}
x即可判断是否为质数.
筛法
结合上一部分,下面提出一个在自然数表中找出质数表的一个改进方法:
- 在 x \sqrt{x} x范围内找出质数;
- 清除这些质数的整数倍;
- 完成.
清
除
所
有
质
数
的
整
数
倍
  
⟺
  
清
除
所
有
合
数
清除所有质数的整数倍\iff 清除所有合数
清除所有质数的整数倍⟺清除所有合数
二者是等价的吗?
下面是解释:
自然的,是一个整数的整数倍的数一定是合数.所以若清除了所有的合数必然清除所有质数的整数倍.由此必要性得证.
下面是充分性:
先引入一个定理:
t
h
e
o
r
e
m
:
∀
x
∈
N
+
x
=
∏
i
=
1
n
a
i
,
a
i
∈
N
+
且
a
i
是
质
数
{theorem:}\\ \forall x \in\mathbb{N+}\\ x=\prod_{i=1}^{n}\ a_i,\\ a_i\in\mathbb{N+}且a_i是质数
theorem:∀x∈N+x=i=1∏n ai,ai∈N+且ai是质数
下面是证明:
p
r
o
o
f
:
对
于
质
数
a
,
可
分
解
为
1
a
˙
,
成
立
.
对
于
合
数
b
,
一
定
可
以
分
解
为
∏
i
=
1
n
m
i
,
m
i
∈
N
+
对
于
m
i
,
若
为
质
数
,
则
分
解
停
止
.
若
为
合
数
,
则
按
照
上
一
条
,
可
以
分
解
为
∏
i
=
1
n
m
i
′
,
m
i
′
∈
N
+
以
上
过
程
均
成
立
直
到
m
i
k
均
为
质
数
.
{proof:} 对于质数a,可分解为1\dot a,成立.\\ 对于合数b,一定可以分解为\\ \prod_{i=1}^{n}\ m_i,m_i\in\mathbb{N+}\\ 对于m_i,若为质数,则分解停止.\\若为合数,则按照上一条,可以分解为 \prod_{i=1}^{n}\ m'_i,m'_i\in\mathbb{N+}\\ 以上过程均成立直到m^{k}_i均为质数.
proof:对于质数a,可分解为1a˙,成立.对于合数b,一定可以分解为i=1∏n mi,mi∈N+对于mi,若为质数,则分解停止.若为合数,则按照上一条,可以分解为i=1∏n mi′,mi′∈N+以上过程均成立直到mik均为质数.
于是
∀
a
i
s
合
数
∃
m
i
s
质
数
m
∣
a
\forall a\ is\ 合数\\ \exists m\ is\ 质数\\ m|a\\
∀a is 合数∃m is 质数m∣a
充分性得证.
那么:
按照这个方法进行质数的筛选,有:
for(a=1;a<=sqrt(x);a++)
{
if(isPrime_number(a)==1)
{
for(b=2;ab<=x;b++)
{
remove(ab);
}
}
else
{
/*怎么会有else?*/
}
}
就是这样了.