mirror of
				https://github.com/Mabbs/mabbs.github.io
				synced 2025-11-04 01:13:10 +08:00 
			
		
		
		
	
		
			
	
	
		
			100 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
		
		
			
		
	
	
			100 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| 
								 | 
							
								---
							 | 
						|||
| 
								 | 
							
								layout: post
							 | 
						|||
| 
								 | 
							
								title: Python学习笔记 - 求质数
							 | 
						|||
| 
								 | 
							
								tags: [Python, 质数, 学习笔记]
							 | 
						|||
| 
								 | 
							
								--- 
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								  讲真,我酸了……<!--more-->
							 | 
						|||
| 
								 | 
							
								  
							 | 
						|||
| 
								 | 
							
								# 起因
							 | 
						|||
| 
								 | 
							
								  在学习Python的过程中,我和同学举行了一个比赛,大概内容是用Python做一个时间复杂度最低的质数生成器。   
							 | 
						|||
| 
								 | 
							
								  在学校里就是有个好处,学校网络上知网下论文是免费的,我大概的查了一下,好像用埃氏筛法的效率比较高。   
							 | 
						|||
| 
								 | 
							
								  以前我用Linux Shell也写过一个:
							 | 
						|||
| 
								 | 
							
								```shell
							 | 
						|||
| 
								 | 
							
								#!/system/bin/sh
							 | 
						|||
| 
								 | 
							
								max=1000
							 | 
						|||
| 
								 | 
							
								list="2"
							 | 
						|||
| 
								 | 
							
								rlist="2"
							 | 
						|||
| 
								 | 
							
								i=3
							 | 
						|||
| 
								 | 
							
								while [ $i -lt $max ]
							 | 
						|||
| 
								 | 
							
								do
							 | 
						|||
| 
								 | 
							
								[ "$(
							 | 
						|||
| 
								 | 
							
								echo "$list"|while read a
							 | 
						|||
| 
								 | 
							
								do
							 | 
						|||
| 
								 | 
							
								[ "$(($i%$a))" == "0" ]&&{
							 | 
						|||
| 
								 | 
							
								echo "1"
							 | 
						|||
| 
								 | 
							
								break 1
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								done
							 | 
						|||
| 
								 | 
							
								)" == "1" ]||c=$i
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								[ "$bj" == "" -a "$c" != "" ]&&{
							 | 
						|||
| 
								 | 
							
								[ "$((${c}*${c}))" -gt "$max" ]&&bj="1"
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								[ "$c" == "" ]||{
							 | 
						|||
| 
								 | 
							
								[ "$bj" == "1" ]||{
							 | 
						|||
| 
								 | 
							
								list="$list
							 | 
						|||
| 
								 | 
							
								$c"
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								echo "$c"
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								c=""
							 | 
						|||
| 
								 | 
							
								i="$(($i+1))"
							 | 
						|||
| 
								 | 
							
								done
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								  不过效率极低……因为原生Shell是不支持数组之类的东西,所以其实并不能完全使用埃氏筛法……   
							 | 
						|||
| 
								 | 
							
								  
							 | 
						|||
| 
								 | 
							
								# 使用Python做一个
							 | 
						|||
| 
								 | 
							
								  当然Python还是可以用的,于是我理解了一下,做了一个出来:
							 | 
						|||
| 
								 | 
							
								```python
							 | 
						|||
| 
								 | 
							
								maxprime=100000
							 | 
						|||
| 
								 | 
							
								rprimeset=set(range(2,maxprime+1))
							 | 
						|||
| 
								 | 
							
								lprimeset=set()
							 | 
						|||
| 
								 | 
							
								lastprime=0
							 | 
						|||
| 
								 | 
							
								while lastprime<=maxprime**0.5:
							 | 
						|||
| 
								 | 
							
								        lastprime=min(rprimeset)
							 | 
						|||
| 
								 | 
							
								        rprimeset=rprimeset-set(range(lastprime,maxprime+1,lastprime))
							 | 
						|||
| 
								 | 
							
								        lprimeset.add(lastprime)
							 | 
						|||
| 
								 | 
							
								primelist=sorted(list(rprimeset|lprimeset))
							 | 
						|||
| 
								 | 
							
								print(primelist)
							 | 
						|||
| 
								 | 
							
								#print(primelist,file=open(__file__[:__file__.rfind("/")]+"/prime.txt",'w+'))
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								  这个效率确实比Shell做的好太多了,而且看起来也清晰易懂。在我的电脑上,1000000的质数只需要4s就能算出来   
							 | 
						|||
| 
								 | 
							
								  
							 | 
						|||
| 
								 | 
							
								# 结局
							 | 
						|||
| 
								 | 
							
								  不过我后来在某百科上查了一下他们用埃氏筛做的Python版本……然后我就酸了……他们的代码在我的电脑上只需要0.6s就能跑完1000000的质数……而且我估计他们的空间复杂度还比我小……
							 | 
						|||
| 
								 | 
							
								```python
							 | 
						|||
| 
								 | 
							
								  #    python 原生实现
							 | 
						|||
| 
								 | 
							
								 
							 | 
						|||
| 
								 | 
							
								def primes(n):
							 | 
						|||
| 
								 | 
							
								    P = []
							 | 
						|||
| 
								 | 
							
								    f = []
							 | 
						|||
| 
								 | 
							
								    for i in range(n+1):
							 | 
						|||
| 
								 | 
							
								        if i > 2 and i%2 == 0:
							 | 
						|||
| 
								 | 
							
								            f.append(1)
							 | 
						|||
| 
								 | 
							
								        else:
							 | 
						|||
| 
								 | 
							
								            f.append(0)
							 | 
						|||
| 
								 | 
							
								    i = 3
							 | 
						|||
| 
								 | 
							
								    while i*i <= n:
							 | 
						|||
| 
								 | 
							
								        if f[i] == 0:
							 | 
						|||
| 
								 | 
							
								            j = i*i
							 | 
						|||
| 
								 | 
							
								            while j <= n:
							 | 
						|||
| 
								 | 
							
								                f[j] = 1
							 | 
						|||
| 
								 | 
							
								                j += i+i
							 | 
						|||
| 
								 | 
							
								        i += 2
							 | 
						|||
| 
								 | 
							
								 
							 | 
						|||
| 
								 | 
							
								    P.append(2)
							 | 
						|||
| 
								 | 
							
								    for x in range(3,n+1,2):
							 | 
						|||
| 
								 | 
							
								        if f[x] == 0:
							 | 
						|||
| 
								 | 
							
								            P.append(x)
							 | 
						|||
| 
								 | 
							
								 
							 | 
						|||
| 
								 | 
							
								    return P
							 | 
						|||
| 
								 | 
							
								 
							 | 
						|||
| 
								 | 
							
								n = 1000000
							 | 
						|||
| 
								 | 
							
								P = primes(n)
							 | 
						|||
| 
								 | 
							
								print(P)
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								  感觉好难受,每次在网上搜的代码都比我写的好……算了,反正我也是在学习嘛。   
							 | 
						|||
| 
								 | 
							
								  后来我听说用欧拉筛法的效率更高……可惜我看完后不太理解……质数算法可真是复杂啊……
							 |