博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

例子:循环语句--素数问题

Posted on 2019-09-25 15:40  非我执笔灬  阅读(599)  评论(0编辑  收藏  举报

例子1:判断一个数是不是素数。

首先要了解该题目的意思,什么是素数?除了1和自身能被整除之外,其他数字都不能被整除的数为素数。

方法一:

那么我们可以根据素数的定义来展开程序的构造,1和自身能被整除,假如此数为n,1~n这个范围中可以将1和n视作两个边界,其中的数都不被整除即可,这样的话我们可以使用range()函数和%取模运算来展开代码。

 1 # coding=gbk
 2 while True:
 3  n = int(input("请输入一个整数:"))
 4  if n < 2:
 5    print(str(n),"不是素数也不是合数!")
 6  else:
 7    for i in range(2,n):
 8      m = n % i
 9      if m == 0:
10        print(str(n),"不是素数!")
11        break
12      else:
13        print(str(n),"是素数!")

1是一个边界,做特殊处理,4~5行代码。被除数从2开始算起,range()函数含左不含右,使用for循环挨个去小于n的正整数,n对其一次取模与0作比较,若等于0,进入if,输出不是素数且break终止循环,若不等于0,直接进入else,输出是素数。

在这里要注意一个问题,如下图所示:

程序里的第二个else不是和第二个if一起搭配的,如果写成图中所示,那么会出现错误,9、15等数会显示是素数,但是9、15这些数是会被3和5整除的。那么这个错误是怎么出现的呢?假如n=9,那么,进入for循环后,i取2,9%2不等于0,因此会进入else输出是素数,也就意味着i在range()函数里不会继续走下去,不会继续等于3~8,自然不会有9%3这种判别。因此,上图中的第二个else完全是没有意义的。必须让i遍历完所有的数,被n取模运算后,才能得出是不是素数的结论。

方法二:

第一种方法,逻辑思维很简单,但是如果是一个很大的数值,从2开始逐个寻找被除数,代码的运行速率会明显得降低,那么,我们可以将方法一中的代码进行优化处理。

 

黄色框之内的代码就是优化代码,(n**0.5)+1是对n开方+1,+1的意思是保证有些数开方后的余数可以进1,这里range()函数的取值范围就比第一种方法小得多,运行起来也效率高的多。(n**0.5)+1的前面要记得加上int(),因为这里是整数运算,开方后的数值类型为浮点数,要取其整数部分。

 

例子2:列出10万以内的所有素数。(这里考验的是程序的效率问题)

该例子可以使用例子1中的代码进行修改,如下图所示,这里用到了计时模块,可以看出该代码的运行时间为3.73秒

 1 # coding=gbk
 2 num = int(input('请输入你所需要的数值范围:'))
 3 print('该数值范围内的所有素数为:')
 4 import datetime
 5 # import datetime这里用到了计时模块
 6 start = datetime.datetime.now()
 7 # 开始计时,赋值给start
 8 for a in range(2,num):
 9     for b in range(2,int(a**0.5)+1):
10         if a % b == 0:
11             break
12     else:
13         print(a,end=' ')
14 delta = (datetime.datetime.now() - start).total_seconds()
15 # 结束计时,赋值给delta
16 print()
17 print(delta)
18 
19 # 第9行用到了开方的方法
20 
21 ##################################################
22 D:\untitled\project2\venv\Scripts\python.exe D:/untitled/project2/day1/refefe.py
23 请输入你所需要的数值范围:100000 
24 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 …… 26 0.720588 27 28 Process finished with exit code 0
 1 # coding=gbk
 2 num = int(input('请输入你所需要的数值范围:'))
 3 print('该数值范围内的所有素数为:')
 4 print(2,end=' ')
 5 import datetime
 6 # import datetime这里用到了计时模块
 7 start = datetime.datetime.now()
 8 # 开始计时,赋值给start
 9 for a in range(3,num,2):
10     for b in range(3,int(a**0.5)+1):
11         if a % b == 0:
12             break
13     else:
14         print(a,end=' ')
15 delta = (datetime.datetime.now() - start).total_seconds()
16 # 结束计时,赋值给delta
17 print()
18 print(delta)
19 
20 # 这里注意素数的性质,第9行代码里刨除了2这个特殊情况,以3开始,因为所有的偶数都不是素数,只看奇数即可。
21 # 记得不要忽略2这个特殊情况,第4行代码
22 ################################################
23 D:\untitled\project2\venv\Scripts\python.exe D:/untitled/project2/day1/refefe.py
24 请输入你所需要的数值范围:100000
25 该数值范围内的所有素数为:
26 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 ……
27 0.62263 28 29 Process finished with exit code
# 在这里其实还能进一步的进行代码的优化,将b的for循环的代码(第10行代码)更改一下,for b in range(3,int(a**0.5)+1):变成for b in range(3,int(a**0.5)+1,2):步长为2,这样的话,该代码的效率还会提升。
 1 # coding=gbk
 2 num = int(input('请输入你所需要的数值范围:'))
 3 print('该数值范围内的所有素数为:')
 4 print(2,3,end=' ')
 5 import datetime
 6 # import datetime这里用到了计时模块
 7 start = datetime.datetime.now()
 8 # 开始计时,赋值给start
 9 num = num - num%6
10 for a in range(5,num,6):
11     for b in range(2,int(a**0.5)+1):
12         if a % b == 0:
13             break
14     else:
15         print(a,end=' ')
16     num = a + 2
17     for b in range(2,int(a**0.5)+1):
18         if num % b == 0:
19             break
20     else:
21         print(num,end=' ')
22 delta = (datetime.datetime.now() - start).total_seconds()
23 # 结束计时,赋值给delta
24 print()
25 print(delta)
26 # 这里利用了素数的一个特性,大于等于5的素数一定和6的倍数相邻,代码第9、10行
27 # 要注意5前面的素数要额外输出,代码第4行
28 ###############################################
29 D:\untitled\project2\venv\Scripts\python.exe D:/untitled/project2/day1/refefe.py
30 请输入你所需要的数值范围:100000
31 该数值范围内的所有素数为:
32 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67……
33 0.614633 34 35 Process finished with exit code 0

 

显示10万以内的素数的方法还有很多,通过上述的几种方法来看,减少遍历的数字是提高代码效率的根本,第二种方法只检索奇数,一下就少了很多的遍历次数,第三,四种方法每隔6个数遍历一次,也省略了很多的遍历次数。