十万以内的所有素数

这里主要是要考虑效率问题,在数据规模较大时,如果不考虑算法优化,效率将会非常差。

import time

# 将特殊质数2事先放在列表中
t = [2]
t0 = time.time()
count = 1
# 去掉所有偶数,从3开始迭代,步进为2
for x in range(3, 100000, 2):
    # 所有大于10的质数中,个位数只有1、3、7、9,大于5且以5结尾的整数能被5整除,这里首先过滤掉大于5且以5结尾的整数
    if x > 5 and x % 10 == 5:
        continue
    # 除去2之外,质数的因子中肯定是没有2的,这里去掉所有被除数中的偶数
    # 一个整数的前后对应的两个因子的乘积等于这个整数,所以一个整数如果平方根之前有一个因子,那平方根之后肯定有一个对应的因子,中间是平方根
    # 这里使用平方根极大减小了数据规模,以及减少了大量迭代次数
    for i in range(3, int(x ** 0.5) + 1, 2):
        if x % i == 0:
            break
    # 要格外注意一下这里的else语句的执行逻辑
    # 没有进入for循环、以及for循环正常结束都会执行else语句,如果被break中断,else不会执行
    else:
        count += 1
        t.append(x)

# print(t)
print('花费时间: {}'.format(time.time() - t0))
print('质数个数: {}'.format(count))
print('质数个数: {}'.format(len(t)))
# 花费时间: 0.20165777206420898
# 质数个数: 9592
# 质数个数: 9592

为什么可以只考虑平方根,上面的备注中已经做了说明,这里以100为例解剖一下:

for i in range(2, 100):
    if not 100 % i:
        print(i)

2
4
5
10
20
25
50

100 = 2 x 50
100 = 4 x 25
100 = 5 x 20
100 = 10 x 10

这样很容易看出,在平方根10之前,如果100有一个因子,那么平方根后面一个有一个对应的因子,而平方根`10x10`是临界点。所以被除数可以从平方根处砍掉后面的部分。

由于相差一个指数,一个整数的平方根通常都比自身小很多,数值越大,相差越大。比如100比10大90,10000比100大9900,这样看就发现数据量减少了不止一星半点。

关于for循环中else语句的执行逻辑,简单敲一下就清晰了:

# 没有进入for循环会执行else语句
for i in range(3,2):
    print('a')
else:
    print('b')
# b

# for循环正常结束会执行else语句
for i in range(3,4):
    print('a')
else:
    print('b')
# a
# b

# for循环如果被break中断,else语句不会执行
for i in range(3,5):
    print('a')
    break
else:
    print('b')
# a

参考:
https://docs.python.org/3/reference/compound_stmts.html#the-for-statement
https://www.cnblogs.com/dspace/p/6622799.html

猜你喜欢

转载自www.cnblogs.com/keithtt/p/9419723.html