質數:一個大於1的自然數,除了1和它自身外,不能被其他自然數整除的數叫做質數;否則稱爲合數
最近在一個做題網站中遇到的一個問題,編寫一個函數,通過傳入的參數判斷這個數是不是質數。然後發現了三種解決辦法,下面按照效率高低依次進行分享。歡迎批評指正。
方法一:
根據解釋本身,傳入一個參數num,依次判斷num - 1中是否有num的約數,如果沒有就是質數,否則就是合數。
def is_prime1(num):
i = 2
while i < num-1:
if num % i == 0:
return False
i += 1
return True
第一種辦法需要對小於num 的每一個數進行判斷,效率最低。
方法二:
對傳入的參數num進行因式分解,只判斷左半部分,如果左邊沒有可以被整除的,右邊肯定也沒有。
from cmath import sqrt
def is_prime2(num):
i = 2
tmp = sqrt(num).real
while i <= tmp:
if num % i == 0:
return False
i += 1
return True
方法三:
關於質數的分佈規律,大於等於5的質數一定和6的倍數相鄰,例如5和7 11和13 17和19 等等。證明:x >= 1 將x >= 5 的自然數表示如下:6x -2 ,6x -1,6x ,6x+1 ,6x+2 ,6x+3 ,6x+4 ,6x+5 ,6(x+1) ,6(x+1)+1 .....可以看到,不在6的倍數兩側的可以提去一個公約數:6x -2、6x+2、6x+3、6x+4 等於 2(3x-1) 2(3x+1) 3(2x+1) 2(2x+2)。所以他們一定不是素數,在除去6x本身,顯然,素數要出現只可能出現在6x的兩側。當然也存在6x兩側的也可能不是素數,還需要在判斷一次。而且我們判斷的步長可以改成6,
from cmath import sqrt
def is_prime3(num):
if num in [2,3]:
return True
# 不在6的倍數兩側絕對不是質數
elif (num % 6) != 1 and (num % 6) != 5 or num <= 1:
return False
tmp = sqrt(num).real
i = 5
# 在6的倍數兩側也可能不是質數
while i <= tmp:
if num % i == 0 or num % (i+2) == 0:
return False
i += 6
return True
最後對這三個方法進行性能測試,同時處理100000以內的數
通過耗時對比可以看出來,方法二和方法三相差不是很多,但數據量很多的話差距就會明顯。方法一簡直了。
個人拙見,有更好的解法,歡迎批評指正