python判断质数的函数并输出_Python实践3

这个问题称为质数(Prime)判定问题。给定一个数,判断该数是否为质数。

首先来看下质数的定义:

质数,又称素数,指的是大于1的自然数中,除了1和自身外,无法被其他自然数整除的数。

03264f7a-6813-eb11-8da9-e4434bdf6706.png

与质数相对的概念是合数。

根据定义,我们可以实现如下的is_prime函数。

def is_prime(n):    if not isinstance(n, int) or n < 2:        return False    for i in range(2, n):        if (n % i) == 0:            return False    return True

其中isinstance(n, int)的作用是判断n的类型,如果不是整数(Integer),或者小于2直接返回False。然后是对从2开始到n-1的数字依次进行判断,如果可以整除返回False,如果通过了以上测试则证明是质数,返回True。

让我们简单测试下。

for i in range(10):    print(i, is_prime(i))

将输出

0 False1 False2 True3 True4 False5 True6 False7 True8 False9 False

结果是正确。这种方法非常简单,直观,但是不够高效。它的时间复杂度为O(n)。

接下来让我们来对他进行优化,考虑一个数,它的因子(可以被n整除的数)肯定不会大于n/2,所以可以缩小这个判断的范围。改进后代码如下。

def is_prime(n):    if not isinstance(n, int) or n < 2:        return False    for i in range(2, n//2+1):        if (n % i) == 0:            return False    return True

可以再次验证函数的正确性。没有问题,通过上边的修改,可以更快速的判断质数。但是该方法的时间复杂度依然是O(n)。

如果你再深入的考虑下,其实只需要考虑那些小于等于n的平方根的数。原因是如果n有大于n的平方根的因子,那么一定有小于n的平方根的因子。比如对于64来说,它的平方根是8。64有大于8的因子,如16,32,那么它一定有小于8的因子2, 4,否则不能成立。

根据以上思想,可以进一步优化程序。

def is_prime(n):    if not isinstance(n, int) or n < 2:        return False    for i in range(2, int(n**0.5)+1):        if (n % i) == 0:            return False    return True

通过以上修改可以将时间复杂度降低到O(n**0.5)。

那么下面考虑一个新问题,如果计算小于等于数n的所有素数。

我们可以枚举每个小于等于n的数字,然后利用前面的函数判断是否为质数。

代码如下:

def find_primes(n):    if not isinstance(n, int) or n < 2:        return []    primes = []    for i in range(n+1):        if is_prime(i):            primes.append(i)    return primes

我们可以演算下方法的正确性。

print(find_primes(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]

可以看到该方法是正确的。但是这个方法是时间复杂度是O(n*n**0.5)。

是否可以改进,答案是Yes。

该方法是由希腊数学家埃拉托斯特尼(Eeatosthese)在公元前250年提出。所使用的原理是从2开始,将每个质数的倍数标记成合数。一个素数的所有倍数构成了一个差为此质数的等差数列。最后将那些没有标记为合数的数字输出即为质数。该方法又被称为筛数法。

05264f7a-6813-eb11-8da9-e4434bdf6706.gif

代码如下。

def find_primes(n):    if not isinstance(n, int) or n < 2:        return []    flags = [True] * (n+1)    for i in range(2, int(n**0.5) + 1):        if flags[i]:            for j in range(i*i, n+1, i):                flags[j] = False    return [x for x in range(2, n+1) if flags[x]]

该方法的时间复杂度为O(n)。

在我的笔记本上运行枚举判断法查询小于等于100000的所有质数,需要用229ms,而利用筛数法,仅需要15ms。再次印证了算法的重要性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值