创作计划
为什么创作?不少老师教编程,喜欢拿教大学那一套来教中学生。笔者认为这是不合适的,中学生有中学的学习方法。我认为从数学入手才能让中学生更容易更快地融入编程。
往期回顾01 余数
02 约数与倍数
正文素数的定义是:除1外所有的正整数,如果仅仅能被自身和1整除,那么称为素数;
与素数对应的是合数:除1外所有的正整数,不是素数就是合数。
题1 判断N是不是素数
N = eval(input("请输入一个大于1的正整数:"))
for i in range(2,N):
if N % i == 0:
print(f"{N}是合数")
exit() # 用exit函数,不能用break。
print(f"{N}是素数")
这是根据定义来判断的,但这不是一个最好的办法。
题2 埃氏算法
埃氏指的是埃拉特色尼。埃拉特色尼是古希腊时代的地理学家和数学家,是人类历史上第一个正确测量地球半径的人。
这个算法的精髓在于,判断N是否为素数,不用判断N能否被N-1整除。实际上,过了N的一半,N就没法整除了。如能把10整除(除自身外)的最大的数是5。所以,上述算法,完全可以省下一半的循环,但这还不是最省的。
令a×a≥n,如果n能整除2~a中间的某个整数的话,其商一定在a~n之间;如果n整除a~n之间的某个整数的话,其商一定在2~a之间。所以判断n是否为素数的最省的方法是,看它能否被2~根号n的数整除。
如数字11,它的开方小于4,它不能被2,3整除,因此必为素数。
N = eval(input("请输入一个大于1的正整数:"))
sqrt_N = int(pow(N,0.5))
#int能取出整数部分,如int(1.5)=1。
#int(x),如果x>0,则int相当于向下取整,
#如果x<0,则int相当于向上取整
for i in range(2,sqrt_N 1):
if N % i == 0:
print(f"{N}是合数")
exit()
# 用exit函数,不能用break。
print(f"{N}是素数")
题3 找出100以内的孪生素数
形如(3,5)(5,7)(11,13)的一对素数叫孪生素数。
def is_prime(n):
sqrt_n = int(pow(n,0.5))
for i in range(2,sqrt_n 1):
if n % i == 0:
return False #return让函数直接exit了
return True
prime_list = []
for num in range(2,100):
if is_prime(num) and is_prime(num 2):
#注意and的执行顺序,只要当前一个是True时才会执行后一个
prime_list.append((num,num 2))
print(prime_list)
题4 素数列表
为什么在此提素数列表呢?因为这个是很多精彩常考的题。如找出2019以内所有的素数。
我们用埃氏算法:
- 建立2~N的数字列表
- 从小到大,如果一个数字能被前面的数字整除,就把它删了。
- 当执行到N的开方时,剩下的就是素数了。
如找出10以内的素数。
- 建立数字列表[2,3,4,5,6,7,8,9,10]
- 从2开始,凡是能被2整除(除2外)的就删了,剩下:[2,3,5,7,9]
- 再删除3的倍数,剩下:[2,3,5,7]
- 由于10的开方小于4,所以剩下的列表就是素数列表了。
这个算法适合人计算,对于计算机而言还要谨慎一点,关键点就在于,一个元素被删了之后,列表的下标要向前移动的。所以正确的做法是,从后往前删。
n = 2019
prime_list = list(range(2,n 1)) #建立列表
sqrt_n = int(pow(n, 0.5))
for i in range(2, sqrt_n 1):
length = len(prime_list)
for j in range(length-1,-1,-1):
# 遍历删除列表,要从后往前遍历,否则会导致越界
if (prime_list[j] % i == 0) and (prime_list[j] != i):
prime_list.pop(j)
print(prime_list)
,