一、前言

今天学习视频时课后作业是找出1000以内既是素数又是回文数的数,写代码这个很容易,结果一运行遇到了bug,输出结果跟预期不一样,调试了快30min,再接着一通搜索和回看视频才发现问题所在。所以特地写下来,方便以后查看。问题的关键是判断素数过程中for…else的用法上(具体看后面代码)

二、实现判断素数的功能

质数(Prime number),又称素数,指在大于1的自然数中,除了1和该数自身外,无法被其他自然数整除的数(也可定义为只有1与该数本身两个因数的数)。via——Wikipedia
所以采用穷举法只要在2~n-1的区间,没有一个数能整出n,那么n就是素数。
对2n-1区间进行合理优化,假设x*y=n(x<=y),那么当x和y相等时,x有最大值。即x=y=sqrt(n),所以x的区间就可以限制为2sqrt(n)+1。还有疑问,可以在再多想想,纸上算一算。
因为这里要用到sqrt()方法,所以需要导入math模块。
不多说,直接上代码:

# 求解1000以内的所有素数,正确版本
import math

num = 2
count = 0
list_s = []
max_d = 1000
while num < max_d:
    length = int(math.sqrt(num)+1) # 对遍历范围进行合理优化
    for i in range(2,length): # 注意从2开始
        if num % i == 0:
            break
    else: # 这里的else跟for对齐,而不是跟if,表示只有while顺利执行时,else才执行
        count += 1
        list_s.append(num) # 存入列表
    num += 1
if count == 0:
    print(max_d,'以内没有素数')
else:
    print(max_d,'以内的素数有',count,'个,分别是:',list_s)

输出结果:
Python中回文数和质数问题的解决
这个代码完全没有问题,然后下面给出一个有问题的代码:

# 求解40以内的所有素数,错误版本
import math

num = 2
count = 0
list_s = []
max_d = 40
while num < max_d:
    length = int(math.sqrt(num)+1) # 对遍历范围进行合理优化
    for i in range(2,length): # 注意从2开始
        if num % i == 0:
            break
        else: # 这里的else跟if对齐,会导致一个素数会被写入math.sqrt(n)-1次,同时一些非素数也会被当做素数
            count += 1
            list_s.append(num) # 存入列表
    num += 1
if count == 0:
    print(max_d,'以内没有素数')
else:
    print(max_d,'以内的素数有',count,'个,分别是:',list_s)

输出结果:
Python中回文数和质数问题的解决
所以,一定要认真对待这个else对齐问题。这个在解决素数问题中很重要。

三、实现判断回文数的功能

回文数即从左到右和从右到左一样。如:12321。
方法:

  1. 把已知的num1数反过来,得到num2,如123变为321,采用//10 %10 *10等运算操作,其中还要借助一个临时变量tmp
  2. 判断如果num1 == num 2,则num1是回文数,反之不是
    代码如下:
# 求解1000以内的所有回文数
num = 0 # 这里num从0开始
list_h = []
max_d = 10000
count = 0 

while num < max_d:
    tmp = num
    num_p = 0
    while tmp != 0:
        num_p = num_p*10 + tmp % 10
        tmp //= 10
    if num_p == num:
        list_h.append(num)
        count += 1
    num += 1
        
if count == 0:
    print(max_d,'以内没有回文数')
else:
    print(max_d,'以内的回文数有',count,'个,分别是:',list_h)

四、实现同时判断回文数和质数
需要选择是否嵌套以及先判断回文还是先判断素数,所以又四个版本。大家可以自己思考每个版本的性能上有无区别,占用空间有无区别。因为我也没有太想明白,所以没有放上来。
我写了四个版本,都能实现需求。不过从性能上,在我测试的100-1000000区间,采用嵌套的先求解回文再判断素数要快一些。
不多说,四个版本的代码全部在写下面,可以自行删掉相应的’’'标记进行测试。

'''
# 版本一、求1000以内的回文素数,多层嵌套,先求素数后回文数

import math

num = 2
count = 0
list_s = []
list_sh = []
max_d = 1000
while num < max_d:
    length = int(math.sqrt(num)+1)
    for i in range(2,length):
        if num % i == 0:
            break
    else:
        list_s.append(num)
        tmp = num
        num_p = 0
        while tmp != 0:
            num_p = num_p * 10 + tmp % 10
            tmp //= 10
        if num == num_p:
            list_sh.append(num)
            count +=1
    num += 1
print(max_d,'以内的素数有:',list_s)
if count == 0:
    print(max_d,'以内没有既是素数又是回文数的数')
else:
    print(max_d,'以内既是素数又是回文数的数有',count,'个,分别是:',list_sh)

'''


'''
# 版本二、求1000以内的回文素数,多层嵌套,先求回文数后求素数

import math

num = 2
count = 0
list_h = []
list_hs = []
max_d = 1000
while num < max_d:
    tmp = num
    num_p = 0
    while tmp != 0:
        num_p = num_p * 10 + tmp % 10
        tmp //= 10
    if num == num_p:
        list_h.append(num)
        length = int(math.sqrt(num)+1)
        for i in range(2,length):
            if num % i == 0:
                break
        else:
            list_hs.append(num)
            count +=1
    num += 1
print(max_d,'以内的素数有:',list_h)
if count == 0:
    print(max_d,'以内没有既是素数又是回文数的数')
else:
    print(max_d,'以内既是素数又是回文数的数有',count,'个,分别是:',list_hs)
'''


'''
# 版本三、求1000以内的回文素数,先求素数再求回文数

import math

num = 2
list_s = []
max_d = 1000

while num < max_d:
    length = int(math.sqrt(num)+1)
    for i in range(2,length):
        if num % i == 0:
            break
    else: # 注意这里的else是和for对齐
        list_s.append(num)
    num += 1


count = 0
list_sh = []
for i in list_s:
    tmp = i
    num_p = 0
    while tmp != 0:
        num_p = num_p*10 + tmp % 10
        tmp //= 10
    if num_p == i:
        list_sh.append(i)
        count += 1
        

print(max_d,'以内的素数有:',list_s)
if count == 0:
    print(max_d,'以内没有既是素数又是回文数的数')
else:
    print(max_d,'以内既是素数又是回文数的数有',count,'个,分别是:',list_sh)
'''


'''
# 版本四、求1000以内的回文素数,先求回文数,再求素数

import math

num = 2
list_h = []
max_d = 10000

while num < max_d:
    tmp = num
    num_p = 0
    while tmp != 0:
        num_p = num_p*10 + tmp % 10
        tmp //= 10
    if num_p == num:
        list_h.append(num)
    num += 1


count = 0
list_sh = []
for hn in list_h:
    length = int(math.sqrt(hn)+1)
    for i in range(2,length):
        if hn % i == 0:
            break
    else: # 注意这里的else是和for对齐
        list_sh.append(hn)
        count += 1
        

print(max_d,'以内的回文数有:',list_h)
if count == 0:
    print(max_d,'以内没有既是素数又是回文数的数')
else:
    print(max_d,'以内既是素数又是回文数的数有',count,'个,分别是:',list_sh)
'''

五、总结

这个过程帮助自己更加深刻的理解了if…elif…else 、for…else和while…else以后使用时会更加注意。

相关文章:

  • 2022-02-12
  • 2021-12-04
  • 2021-12-04
  • 2022-01-05
  • 2022-12-23
  • 2021-10-20
  • 2021-08-22
  • 2021-08-05
猜你喜欢
  • 2021-08-10
  • 2022-12-23
  • 2021-12-25
  • 2021-10-07
  • 2022-12-23
  • 2021-12-18
相关资源
相似解决方案