日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

1亿以内素数的个数_算法|找出给定范围的所有素数

發布時間:2025/3/15 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 1亿以内素数的个数_算法|找出给定范围的所有素数 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
本文參考C++版本:如何高效判定、篩選素數

給定n,我們如何輸出n以內(不含n)的所有素數?

使用Python,完成函數體,要求返回n以內的素數個數和這些素數。

def countPrimes(n):"""itype -> intrtype -> intrtype -> list"""關于評價算法速度:如何計算時間復雜度

1.直覺算法

按部就班地遍歷2到n-1,依次判斷素數。

def countPrimes(n):primes = []if n < 2:return 0, primesfor i in range(2,n):if isPrime(i):primes.append(i)return len(primes), primesdef isPrime(k):"""itype: int, >=2rtype: int"""r_isPrime = Truefor i in range(2,k):if k%i == 0:r_isPrime = Falsereturn r_isPrime from time import process_time t1 = process_time() n = int(input("Input a positive integer: ")) count_primes, primes = countPrimes(n) t2 = process_time()print("The number of primes within {} is {}:".format(n,count_primes)) print("Elapsed time: {}".format(t2-t1)) Input a positive integer: 10000The number of primes within 10000 is 1229: Elapsed time: 2.875

評價

直接地,得到時間復雜度(時間復雜讀不考慮系數):

但是這樣地算法存在冗余,太耗時了。 對n=20,我們只需要檢查

  • 20=2*10
  • 20=4*5
  • 20=
  • 20=5*4
  • 20=10*2 觀察到只需要檢查20在小于 中的正整數中是否找能被整除的因數,找不到那么后面一半也找不到,找到了就直接判斷為素數。

2.平方根算法

檢查數k時,遍歷因數i范圍為

。def isPrime(k):"""itype: int, >=2rtype: int"""r_isPrime = Truefor i in range(2,int(k**0.5)+1):if k%i == 0:r_isPrime = Falsereturn r_isPrime from time import process_time t1 = process_time() n = int(input("Input a positive integer: ")) count_primes, primes = countPrimes(n) t2 = process_time()print("The number of primes within {} is {}:".format(n,count_primes)) print("Elapsed time: {}".format(t2-t1)) Input a positive integer: 10000The number of primes within 10000 is 1229: Elapsed time: 2.5625

評價

發現優化得效果也沒好多少,用時減少一丁點。函數isPrime()時間復雜度為

。 發現其實還有冗余,如果已知2為素數,那么就不應該多余地去檢查4,6,8這些2的倍數。按照這樣的原理,演化到下一個算法。

素數篩-Sieve of Eratosthenes

篩掉已知素數的倍數。

def countPrimes(n):if n < 2:return 0, primesprime_sieve = [1]*nprime_sieve[0:2] = [0,0]for i in range(2, n):if prime_sieve[i]:for j in range(i*2, n, i):prime_sieve[j] = 0return prime_sieve.count(1), [index for index,value in enumerate(prime_sieve) if value == 1] from time import process_time t1 = process_time() n = int(input("Input a positive integer: ")) count_primes, primes = countPrimes(n) t2 = process_time()print("The number of primes within {} is {}:".format(n,count_primes)) print("Elapsed time: {}".format(t2-t1)) Input a positive integer: 1000000The number of primes within 1000000 is 78498: Elapsed time: 0.28125

篩掉倍數后,算法表現提升顯著,還有可以提升的空間。 - for i in range(2, n):是在遍歷所有小于n大于等于2的正整數,當n=20,我們不需要遍歷所有的大于

的正整數,因為不是素數的肯定通過遍歷前面一半的時候篩掉了,是素數的素數篩值保持不變。那么可以將遍歷范圍變為 。def countPrimes(n):if n < 2:return 0, primesprime_sieve = [1]*nprime_sieve[0:2] = [0,0]for i in range(2, int(n**0.5)+1):if prime_sieve[i]:for j in range(i*2, n, i):prime_sieve[j] = 0return prime_sieve.count(1), [index for index,value in enumerate(prime_sieve) if value == 1]from time import process_time t1 = process_time() n = int(input("Input a positive integer: ")) count_primes, primes = countPrimes(n) t2 = process_time()print("The number of primes within {} is {}:".format(n,count_primes)) print("Elapsed time: {}".format(t2-t1)) Input a positive integer: 1000000The number of primes within 1000000 is 78498: Elapsed time: 0.1875

OHHHHHHHHHHHHHHHH 外層的循環范圍優化了,現在考慮內層循環for j in range(i*2, n, i):。 當n=20,i=5時會篩掉10,15,20,25...,但是這10,15,20已經被素數2,3篩掉。小于當前素數的因數,要么是更小的素數,要么是更小的素數的倍數,當前素數與這些因數相乘,肯定被篩過了,所以只需要從

開始檢查。def countPrimes(n):if n < 2:return 0, primesprime_sieve = [1]*nprime_sieve[0:2] = [0,0]for i in range(2, int(n**0.5)+1):if prime_sieve[i]:for j in range(i**2, n, i):prime_sieve[j] = 0return prime_sieve.count(1), [index for index,value in enumerate(prime_sieve) if value == 1]from time import process_time t1 = process_time() n = int(input("Input a positive integer: ")) count_primes, primes = countPrimes(n) t2 = process_time()print("The number of primes within {} is {}:".format(n,count_primes)) print("Elapsed time: {}".format(t2-t1)) Input a positive integer: 1000000The number of primes within 1000000 is 78498: Elapsed time: 0.15625

時間復雜度為:

.

評價

以此來看,本文截至此處目前最好的素數算法為Sieve of Eratosthenes。代碼:

def countPrimes(n):if n < 2:return 0, primesprime_sieve = [1]*nprime_sieve[0:2] = [0,0]for i in range(2, int(n**0.5)+1):if prime_sieve[i]:for j in range(i**2, n, i):prime_sieve[j] = 0return prime_sieve.count(1), [index for index,value in enumerate(prime_sieve) if value == 1]

Euler's Sieve

現在介紹一個有線性時間復雜度$mathcal{O(n)}$的算法:歐拉篩法。

算法:

整個過程為:

def countPrimes(n):if n < 2:return 0, primescur_list = list(range(2, n))primes = []while True:cur_prime = cur_list[0]backup_list = cur_list.copy()for j in backup_list:if j*cur_prime not in cur_list:breakcur_list.remove(j*cur_prime)primes.append(cur_prime)cur_list.pop(0)if cur_prime**2 > n:primes.extend(cur_list)breakreturn len(primes), primesfrom time import process_time t1 = process_time() n = int(input("Input a positive integer: ")) count_primes, primes = countPrimes(n) t2 = process_time()print("The number of primes within {} is {}:".format(n,count_primes)) print("Elapsed time: {}".format(t2-t1))Input a positive integer: 1000 The number of primes within 1000 is 168: Elapsed time: 0.013890345999996612
Input a positive integer: 10000 The number of primes within 10000 is 1229: Elapsed time: 0.36447122299999535
Input a positive integer: 100000 The number of primes within 100000 is 9592: Elapsed time: 49.40181045400001

根據對區區10000的輸入,我寫的算法就表現得不太行,實際上輸入1000000就接近崩潰了,算法本身沒問題,我實現的代碼不夠還原,肯定有很多冗余。這兩天折騰夠了,以后再看看。


Changelog

  • 2020/04/03: 感謝評論區 @天空和云 的提醒,修改了兩處代碼。
  • 2020/02/15: 更新了歐拉篩法,思路正確但是代碼有缺陷。

總結

以上是生活随笔為你收集整理的1亿以内素数的个数_算法|找出给定范围的所有素数的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。