在数论中有一个很重要的概念—素数(primenumber),素数也叫质数,它是指在自然数中,除了0、1以外,不能被其他自然数整除的数。
自然数相反,能被其他自然数整除的数,我们称之为合数。这里,0、1既不是素数,也不是合数。素数和合数的定义是数论中最基础的定义之一。
质数与合数著名的哥德巴赫猜想,就是基于质数定义的基础之上建立的问题。今天,我们来探讨如何利用Python判断素数?有下面几个方法。
方法一:利用math模块中sqrt函数
这里思路很简单,不做过多解释。直接上代码
利用math模块判断看下程序运行效果
0不是素数1不是素数2是素数3是素数4不是素数5是素数6不是素数7是素数8不是素数9不是素数
可以判断0-9之间的自然数是否为素数。
直接描述方法二:单行程序扫描
其实,这个问题可以用一句话搞定
importmath
defisPrimeNumber(n):
returnFalseif0in[n%iforiinrange(2,int(math.sqrt(n))+1)]elseTrue
但这样没有考虑0、1的情况,我们需要加上这两种特殊情况。代码及运行效果如下
一行代码搞定核心操作方法一、二基本类似。但方法二可读性稍微差点。
对比方法三:不使用math模块
不使用math模块,这里思路很简单,就是我们先判断0、1、2、偶数等这些特殊的自然数。这些很好判断
n=:n==:n%==:那么还剩下的都是3以上的奇数了(定义为i),然后判断i*i是否小于n,如果小于n,则判断i是否能被n整除,如果可以被整除,则返回False(即该数不是素数);如果不能被n整除,增i+2后,再次进入循环。有点乱,我们看下代码
(n):n=:n==:n%==:i=i*i=n:n%i==:i+=__name__==:numberlst=[ii(,)]numnumberlst:(.format(num,isPrimeNumberpro(num)))截图方便缩进
另一种方法方法三其实并没有做多大改变,它是将sqrt进行了分解,把for循环转写为while循环,但这里可取的是先排除0、1、2、偶数,并且将这些语句放在循环遍历之前,这样可以大量节约程序运行时间。试想,如果将这些判断全部加入到循环内,是不是不太好?我们下文会有验证!
这个方法更节约时间网上还有很多类似的方案,但个人觉得这些方法都大同小异。这里就不再一一赘述了。下面,我们来对比下哪个程序更优一点?
终:性能测试
我们在程序中加入下面这个装饰器函数
timefunctoolswraps(function):(function)(*args,**kwargs):sta_t=time.time()i():function(*args,**kwargs)end_t=time.time()(.format(function,(end_t-sta_t)))function_timer这个装饰器的作用是记录函数运行万次的时间。然后,在每一个函数定义前加上
fn_timer,依次运行函数,我们得到如下结果运行程序functionisPrimeNumberat0xD7FC总计花费时间1.秒运行程序functionisPrimeNumberproat0xD7FC总计花费时间2.秒运行程序functionisPrimeNumberpro2at0xD7FC总计花费时间0.秒
出人意料的结果哪一个运行速度快?一目了然,但结果却出乎我们意料之外,偏偏while循环遍历耗费的时间少,这是为什么呢?这个问题留给大家,欢迎小伙伴留言讨论……
好了今天的内容就到这里了,喜欢Python编程的小伙伴