转自同名微信公众号
接上题:打印出100~1000里的所有素数,并打印出素数的个数。
判断数字n是否是素数在第7课学过。
n = 61199293
for i in range(2,n):
if n % i == 0:
print(i)
print('n is not a prime number')
break
循环嵌套在第8课学过。
for i in range(100,1001):
for j in range(2,i):
if i % j == 0:
print(i)
print('n is not a prime number')
break
但上面的程序只能把非素数打印出来。
怎么打印范围内的素数,以及统计出素数的个数?
介绍2种常用的方法。
使用标示变量
count = 0
for i in range(100,1001):
flag = True
for j in range(2,i):
if i % j == 0:
flag = False
break
if flag:
count += 1
print(i)
print(count)
在i循环里面,添加 flag = True,作用是默认i 是素数。
然后进入 j 的循环,如果 i 不是素数, flag = False。
要注意理解的是
1. flag = True要放在i循环里面,才能保证i循环的每一个数字,都先默认成素数。
2. if flag 和 for j 语句缩进保持一致,才能保证两个语句的地位相等。if 语句始终被执行。
循环里的else
count = 0
for i in range(100,1001):
for j in range(2,i):
if i % j == 0:
break
else:
count += 1
print(i)
print(count)
循环语句里的else是Python语言特有的,有趣的语法。
思考:为什么我们会碰到文章开头的问题?无法把素数打印出来?
程序中,我们通过for j 循环来判定一个数是否是素数。有2种情况会使得for j 循环结束。一种是自然结束,也即范围内的都循环完了。一种是break结束。
当for j 循环是自然结束时,i是素数。可问题在于:在for j 循环的外部,我们无法得知for j循环是怎么结束的。
第一个方法里的flag是通过在满足break的情况下,改变flag的值,从而在for j循环外部,可以通过判断flag的值是否被改变而获知for j循环是如何结束的。其它编程语言一般用这种方法。
而Python则在循环语句里引入了 else语法,实现更为简洁。
当一个循环是自然结束(也即没有被break结束)时,就会执行其匹配的else语句。
while循环
一般情况下,我们习惯使用for循环。但有些时候,我们不得不使用while循环。比如说,我们无法得知,或者很难得知要循环多少次时。
分解质因数
每个合数都可以写成几个质数相乘的形式,其中每个质数都是这个合数的因数,把一个合数用质因数相乘的形式表示出来,叫做分解质因数。如30=2×3×5 。分解质因数只针对合数。
数学上,我们使用短除法分解质因数。
设 n = 90, 短除法的过程如下图。
如上图可知,程序需要2层循环。
外层循环将n不断除以其最小质因数,直到n等于1。
90 --> 45 --> 15 ……
这个过程当然也可以用for循环来做,但显然用while循环要更容易理解。
while n > 1:
n = n 除以(n的最小质因数)
内层循环就是每次寻找n 的最小质因数。
根据数学知识,[2,n]中,第一个能够整除n的数,就是n的最小质因数。
(简单证明:假设 x 是 [2,n]里第一个能够整除n的数,它自然是最小的因数。
反证法,如果 x 不是质数,x = a * b,那么 a,b显然也能整除n,且都比x小,由此可证假设不成立。)
for i in range(2,n+1):
if n % i == 0 :
i就是n的最小质因数
break
所以,完整的程序就是
n = 90
while n > 1:
for i in range(2,n+1):
if n % i == 0:
n = int(n/i)
print(i)
break
一道再熟悉不过的习题
两个没有刻度的水杯 a,b。其中a水杯容量是3升,b水杯容量是5升。
还有一个足够大的,只能装水,不能倒水出来的水杯c。
假设有无限量的水,且不考虑水在杯子间倒来倒去会有损失。
问题1:能否用a,b两个杯子往水杯c里倒入正好4升水?
问题2:假设a水杯容量为x,b水杯容量为y,要往c水杯倒入z升水。给定任意的x,y,z。用python程序判断是否可行。
提示:只需要判断是否可行,不需要给出步骤。