质数相关算法:统计小于整数n的质数个数

问题:现给定一个大于1的整数 N,求出小于N 的质数的个数。

例如:
输入 10
输出:4(2,3,5,7)
输入:20
输出: 8(2,3,5,7,11,13,17,19)

以下介绍5种算法,前3种思路一致,主要是效率的差异;

第5种采用了埃拉托斯特尼筛法进行计算(比较巧妙)

算法1:

针对小于N的每个正整数x,我们可以遍历从2到x-1遍历去试除,当出现一个数能被整除,那这个数就不是质数;当然这种方法也是最容易想到的方法,但效率也是最低的方法;

代码如下:

def prime(n):
    m = 0
    for i in range(2, n):
        j = 2
        for j in range(2, i-1):
            if i % j == 0:
                break
        else:
            m += 1
    return m

算法2:

我们可以遍历从2到x/2的数去试除,这样子相对于第一种方法节省了近一半的时间;

代码如下:

def prime(n):
    m = 0
    for i in range(2, n):
        j = 2
        for j in range(2, int(i/2)+1):
            if i % j == 0:
                break
        else:
            m += 1
    return m

算法3:

我们可以针对第二种算法进一步优化,遍历从2到√x;

因为数学的因数都是成对出现的,如果出现一个大于√x的因数,必然有一个小于√x的因数存在,因此我们遍历到√x就可以判定一个数是不是质数;

例如:16,   1*162*84*4

代码如下:

def prime(n):
    m = 0
    for i in range(2, n):
        j = 2
        for j in range(2, int(i**0.5)+1):
            if i % j == 0:
                break
        else:
            m += 1
    return m

算法4:

对于任意一个大于3的合数(除了1和自身外,还能被其他整数整除的数),我们都可以将其拆分成至少包含一个质数的因子相乘;
例如:8=2 x 4(2是质数),9=3 x 3;
因此,我们可以采用遍历小于这个数的所有质数来确认这个数是不是质数。

代码如下:

def prime(n):
    if n <= 2:
        return 0
    else:
        prime_list = list()
        prime_list.append(2)  # 先将2加入到要遍历的列表中
        for x in range(3, n):
            y = False  
            for y in prime_list:
                if x % y == 0: # 对小于n的x进行遍历,当某个数整除为0时,不执行添加列表操作
                    y = False
                    break
                else:
                    y = True
            if y is True:
                prime_list.append(x)  # 对小于x的质数进行遍历后,没有能整除的质数,则这个数也是质数
        return len(prime_list)

算法5:

埃拉托斯特尼筛法:

从2开始,将每个素数的各个倍数,标记成合数。一个素数的各个倍数,是一个差为此素数本身的等差数列。此为这个筛法和试除法不同的关键之处,前者是先找出所有合数,最后再剔除掉这些合数,得到所有素数。后者是逐一尝试每个待测数能否被大于2且小于它的整数整除,直接判断是否为素数。(摘自维基百科)

具体的实现方式:
先留下第一个素数2,将所有2的倍数的合数全部剔除;下一个素数3,将3的倍数的所有合数全部剔除;接着用5进行筛选剔除;当所要使用的素数的平方大于设定值时,停止筛选,则剩下的所有数均为素数。

例如:求出小于120的所有素数,依次使用2,3,5,7进行筛选,当到11时,11*11>120,停止筛选,剩余数即为质数。

这个代码写法非常巧妙,先用列表is_right ,存放n个True,代表小于n的所有数我们先看成质数,过程中判断为质数倍数的(也就是合数),用is_right[i],巧用下标改为Fasle

def prime(n):
    if n <= 2:
        return 0
    is_right = [True] * n
    is_right[1] = False
    for i in range(2, int(n ** 0.5) + 1):
        if is_right[i]:
            for j in range(i * i, n, i):
                is_right[j] = False
    m = 0
    for x in range(2, n):
        if is_right[x]:
            m += 1
    return m
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值