【本文结构】
- 题目信息:来源、地址、序号、描述
- 题目答案:简要分析,程序代码(测试运行通过,含注释),运行结果
- 霍霍磨刀:解答这道题目之前应掌握的知识基础
- 解析过程:题目类型,分析以及实践过程
- 斩获成果:通过解答这道题目之后的知识提升
- 下一题预告:来源、地址、序号、描述
【题目信息】
描述:判断101-200之间有多少个素数,并输出所有素数
【题目答案】
程序分析:判断素数的方法:用一个数分别去除2到sqrt(这个数),如果能被整除,则表明此数不是素数,反之是素数。
程序代码(菜鸟教程上的答案):
h = 0 # 定义变量h,并赋初值为0,计算素数总数
leap = 1 # 定义变量leap,并赋初值为1,作为标记,判断是否为素数from math import sqrt # 从math库中导入sqrt函数:开平方from sys import stdout # 从sys库中导入stdout函数:输出for m in range(101,201): # 循环101到200之间
k = int(sqrt(m + 1)) # 开平方并取整for i in range(2,k + 1): # 循环2到开方数if m % i == 0: # 如果取余为0
leap = 0 # 那么设置变量leap为0break # 跳出循环if leap == 1: # 如果变量为1
print('%-4d' % m) # 输出素数
h += 1 # 素数数量加1if h % 10 == 0: # 如果数量为10的倍数
print() # 则输出空行
leap = 1 # 恢复leap标记为1
print('The total is %d' % h) # 输出素数总数为h
运行结果:
101
103
107
109
113
127
131
137
139
149
151
157
163
167
173
179
181
191
193
197
199
The total is 21
【霍霍磨刀】
在解答这道题目之前,你首先应具备以下知识基础:
- for循环结构的使用
- 素数的概念,素数举例
【解析过程】
题型:{语法描述题}
- 解题(分步实施)
- 如何用程序来判断一个数是素数
判断一个数是不是素数,用该数逐个除以比它小的数,如果能整除,则不是素数,否则就是素数,代码如下:
flag=1 # 定义变量flag,赋初值为1,用于判断是否为素数,1:素数,0:不是素数
n=int(input("请输入一个数:")) # 输入一个数for i in range(2,n): # 循环2到该数之间的数if n % i==0: # 依次判断取余是否为0
flag=0 # 如果可以取余为0,则设置标记为0break # 跳出循环if flag==1: # 如果标记为1
print("{}是素数".format(n)) # 则该数为素数else: # 否则
print("{}不是素数".format(n)) # 该数不是素数
- 如果循环100到200之间的数
循环100到200,我们可以采用for结构和range函数
for i in range(101,201):
- 如何找出100到200之间的素数
将上述代码合并到一起,也就是把判断素数的代码放到100到200的循环之间,代码如下所示
flag=1 # 定义变量flag,赋初值为1,用于判断是否为素数,1:素数,0:不是素数
for i in range(101,201): # 外循环,循环101到200之间
for j in range(2,i): # 内循环,循环2到i之间
取余j是否为0
flag=0 # 如果为0,则标记flag为0,该数不是素数
break # 跳出内循环
if flag==1: # 如果flag为1,则为素数
print(i) # 输出该数
flag=1 # 重置flag标记为1
- 如何统计素数总数
定义一个变量n,每次找到一个素数,变量n加上1,即可,代码如下
flag=1 # 定义变量flag,赋初值为1,用于判断是否为素数,1:素数,0:不是素数
n=0 # 定义变量n,赋初值为0,用于统计素数总数for i in range(101,201): # 外循环,循环101到200之间for j in range(2,i): # 内循环,循环2到i之间if i % j ==0: # 判断i取余j是否为0
flag=0 # 如果为0,则标记flag为0,该数不是素数break # 跳出内循环if flag==1: # 如果flag为1,则为素数
print(i) # 输出该数
n+=1 # 素数数量加1
flag=1 # 重置flag标记为1
print("101到200之间的素数总数为:",n) # 输出素数总数为n
解答完毕
- 优解(优化解题)
经过上述的解答,基本答案已经出来,但从编程学习角度来讲,我们还可以进行优化
- 关于遍历次数
修改上述代码,加入一个变量p,用来统计两次循环下的运行次数,代码如下所示:
flag=1 # 定义变量flag,赋初值为1,用于判断是否为素数,1:素数,0:不是素数
n=0 # 定义变量n,赋初值为0,用于统计素数总数
p=0 # 记录遍历次数for i in range(101,201): # 外循环,循环101到200之间for j in range(2,i): # 内循环,循环2到i之间
p+=1 # 遍历次数加1if i % j ==0: # 判断i取余j是否为0
flag=0 # 如果为0,则标记flag为0,该数不是素数break # 跳出内循环if flag==1: # 如果flag为1,则为素数
print(i) # 输出该数
n+=1 # 素数数量加1
flag=1 # 重置flag标记为1
print("101到200之间的素数总数为:",n) # 输出素数总数为n
print("遍历次数为:",p) # 输出遍历次数
在运行结果中,可以看到:
遍历次数为: 3291
而在网站提供的答案代码的相同位置加上p,代码如下:
h = 0 # 定义变量h,并赋初值为0,计算素数总数
leap = 1 # 定义变量leap,并赋初值为1,作为标记,判断是否为素数
p=0from math import sqrt # 从math库中导入sqrt函数:开平方from sys import stdout # 从sys库中导入stdout函数:输出for m in range(101,201): # 循环101到200之间
k = int(sqrt(m + 1)) # 开平方并取整for i in range(2,k + 1): # 循环2到开方数
p+=1if m % i == 0: # 如果取余为0
leap = 0 # 那么设置变量leap为0break # 跳出循环if leap == 1: # 如果变量为1
print('%-4d' % m) # 输出素数
h += 1 # 素数数量加1if h % 10 == 0: # 如果数量为10的倍数
print() # 则输出空行
leap = 1 # 恢复leap标记为1
print('The total is %d' % h) # 输出素数总数为h
print("遍历次数为:",p) # 输出遍历次数
运行结果却是:
遍历次数为: 392
这是什么原因呢,其实与内循环的素数判断代码的范围不一致有关,回到如何判断是素数上来看,如何判断一个数是素数,我们一般是这么理解,将该数除以比它小的数,如果都无法整除,则该数是素数,其实没必有一直去除,只需要除到一定的数即可,那这个数是多少,是它的开方数
举个例子,判断13是否是素数,我们写一段代码,如下所示
n=13for i in range(2,n):
print("{}//{}={}".format(n, i, n//i))运行结果:
13//2=6
13//3=4
13//4=3
13//5=2
13//6=2
13//7=1
13//8=1
13//9=1
13//10=1
13//11=1
13//12=1
它的被除数和商中总有一个数在它的开方数以下,也就是换句话说,当13除以3无法进行整除的话,那么后续的除法其实都是没有必要的,做的是无用功。
因此,我们引入math库中的sqrt函数,改动内循环的最高值,代码如下
from math import sqrt # 从math库中导入sqrt函数:开平方
flag=1 # 定义变量flag,赋初值为1,用于判断是否为素数,1:素数,0:不是素数
n=0 # 定义变量n,赋初值为0,用于统计素数总数
p=0 # 记录遍历次数for i in range(101,201): # 外循环,循环101到200之间
k = int(sqrt(i)) # 开平方并取整for j in range(2,k+1): # 内循环,循环2到i之间
p+=1 # 遍历次数加1if i % j ==0: # 判断i取余j是否为0
flag=0 # 如果为0,则标记flag为0,该数不是素数break # 跳出内循环if flag==1: # 如果flag为1,则为素数
print(i) # 输出该数
n+=1 # 素数数量加1
flag=1 # 重置flag标记为1
print("101到200之间的素数总数为:",n) # 输出素数总数为n
print("遍历次数为:",p) # 输出遍历次数
运行结果中:
遍历次数为: 392
可以看到运行次数大幅减少,运行效率大幅提升
- 关于输出显示
将
print(i) # 输出该数
修改为
print(i,end=",") # 输出该数
将每行一个的显示改为逗号分割,可方便查看
- 采用过滤函数filter来实现找素数
在一段数当中找到符合条件的数,其实我们可以利用python中的高阶函数filter函数来实现,实现代码如下
def is_prime(n):for s in range(2, n):if n % s == 0:return False return True
tmplist = filter(is_prime,range(101,201))
newlist = list(tmplist)
print(newlist)
【斩获成果】
这题在编程中属于基本的语法结构和对数学定义的理解题,偏简单型,在曾经vb的教学过程中,对于定义一个flag无法理解,其实我们把它理解为一个开关,一个标记,一个符合条件的球都可以。
通过这题的学习,我们学会了如何更好地去找出素数,并尝试探索了高阶函数filter的运用。
解决这样的程序,可以通过先遍历,再判断的方式来解决。
举一反三,抛出问题:
- 找出100到200之间能被7整除的数
- 找出100到200之间中带数字3的数字