fsword's blog

A blogging framework for hackers.

如何求素数(1)

| Comments

学习语言的过程是比较枯燥的,不过我们可以拿来做一些有趣的事情,在解决具体问题的过程中熟悉语言。
例如我们可以来练习一下这个问题

找出小于N所有素数

首先复习一下学校里的知识——

  • 素数(也称质数),指的是一类大于1的自然数,这些自然数有个特点,除了1和它自身,它们不能被其它的任何自然数整除。
1
2
3
举例:  
    4不是素数,因为它可以被2整除;  
    11是素数,因为除了1和它自身,它不能被其它自然数整除;
  • 判断一个数是否是素数,最直接的方法就是检查所有大于2小于它的自然数能否被它整除,更进一步,最大除数只要达到N的平方根就行了

根据上述知识,我们可以找到问题的解决思路。方法如下:

1. 将N以内的所有整数列出来
2. 标出序列中的第一个素数(比如:2),然后将后续中能够被这个素数整除的成员删除
3. 对新的序列重复执行上述步骤,循环进行,循环次数不大于N的平方根

上述解法其实是这个问题最古老(可能也是最高效)的方法——“筛法(Sieve of Eratosthenes)”,是由古希腊数学家埃拉托斯特尼发明的

根据这些知识,我们可以写出ruby版的实现

执行一下:

1
2
1.9.3p194 :008 > prime 100
 => [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]

成功!
是不是很简单?但是且慢,算出来需要多久呢?要是几百万以内的素数,又需要多长时间呢?
写一段代码验证一下(我们计算结束后不输出,这是为了避免大量数据输出对IO的压力)

执行结果(修改了一下格式)——

1
2
3
4
5
$ ruby prime_benchmark.rb
       user      system       total        real
       10000     0.020000     0.000000   0.020000   (  0.024682)
       100000    1.410000     0.010000   1.420000   (  1.419806)
       1000000   245.320000   0.060000   245.380000 (246.231597)

从10万到100万,耗时增加了200倍!!! 检查load和CPU占用率,发现load不高,但是有一个cpu核心占用率100%,这说明cpu的计算能力没有得到平衡使用,这个问题我们下一阶段解决

Comments