十萬之內的全部素數

這裏主要是要考慮效率問題,在數據規模較大時,若是不考慮算法優化,效率將會很是差。html

import time

# 將特殊質數2事先放在列表中
t = [2]
t0 = time.time()
count = 1
# 去掉全部偶數,從3開始迭代,步進爲2
for x in range(3, 100000, 2):
    # 全部大於10的質數中,個位數只有一、三、七、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爲例解剖一下:python

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
http://www.javashuo.com/article/p-sldlphrt-cy.htmlapp

相關文章
相關標籤/搜索