求 素数的几种算法(位图法,多线程)

本文介绍了如何利用位图法和多线程来求解大范围内的素数。在面对1到1000万的素数计算时,通过原子操作确保多线程任务分配的公平性,尽管这可能导致多线程效率低于单线程。另一种方案是忽略任务的精确均分,直接按线程数量分配任务。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

据说某公司面试,问了10几个人竟然没人会求1-100间的素数

 

下面我们举例 写个从1到1000w之间素数的算法

 

最朴素的算法

package Algorithm.DP;

public class Prime {
	 int count=4;
	
	public   boolean isPrime(int i){
		if(i%2==0)
			return false;
		if(i%3==0)
			return false;
		if(i%5==0)
			return false;
		if(i%7==0)
			return false;
		
		for(int j=8;j*j<=i;j++){
			if(i%j==0)
					
				return false;
		
		}
		count++;
		return true;
		
	
	
	}
	public static void main(String [] args){
		Prime prime=new Prime();
		int [] array=new int[10000002];
		for(int i=0;i<array.length;i++)
			array[i]=i;
		
		long startTime=System.currentTimeMillis();
		for(int i=2;i<array.length;i++)
			prime.isPrime(array[i]);
		
		System.out.println("共有素数个数"+prime.count+"  计算花费时间"+(System.currentTimeMillis()-startTime));
			
		
		
	}
	

}


位图法

package ProgrammingPearls;

public class Prime {
	private final int MAX_SIZE=10000002;
	private final int n=MAX_SIZE-2;
	private int count;
	private long startTime;
	char[] array=new char[MAX_SIZE];
	public Prime(){
		for(int i=2;i<MAX_SIZE;i++)
			array[i]=1;	
		array[1]=0;
		count=0;
        startTime=System.currentTimeMillis();
	}
	public void getPrime(){
		int p=2;
		while(p<=n){
			count++;
			for(int i=p;i<=n;i=i+p)
				array[i]=0;
			do{
				p++;
				
			}while(array[p]==0);
						
		}
		
		System.out.println("此次计算用时"+(System.currentTimeMillis()-startTime)+"共有素数"+count);
		
	}
	public static void main(String [] args){
		
		Prime prime=new Prime();
		prime.getPrime();
		
		
		
		
		
	}

}


多线程 。因为每个区间之间素数个数不均分,切大数时计算复杂度不同个,为了保证每个线程任务均分,我使用了原子操作,不断给被测数+1并分发给多个线程,这样因为原子操作开销太大,导致多线程的结果比单线程还要慢。

可以不考虑多个线程之间任务是否均分 ,直接开辟不同数量的线程均分任务。

 

 

package Algorithm.DP;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.*;

public class Concurrency implements Runnable{
	    
	static   AtomicInteger count;
	private final CountDownLatch latch;
    private	Counter counter;
    public Concurrency(Counter counter,CountDownLatch latch){
    	     this.latch=latch;
	    	count=new AtomicInteger(4);
	    	this.counter=counter;
	   
	    }
		public   boolean isPrime(long temp){
			if(temp%2==0)
				return false;
			if(temp%3==0)
				return false;
			if(temp%5==0)
				return false;
			if(temp%7==0)
				return false;
			
			for(int j=8;j*j<=temp;j++){
				if(temp%j==0)
						
					return false;
			
			}
			return true;
		}
			
		


	@Override
	public void run() {
	
		   while(!Thread.interrupted()){
			   
			   long temp=counter.nextNum();
		
			   if(temp==0)
				  Thread.currentThread().interrupt();
			   else
			   {   
				   if(isPrime(temp))
				   {		   
				   count.incrementAndGet();
				   }
				   
			   }
			   
		   }
		   latch.countDown();
		 
		
	}	
	
		

	public static void main(String [] args) throws InterruptedException{
		    int numOfThreads=3;
		    long startTime=System.currentTimeMillis() ;
		    CountDownLatch latch=new CountDownLatch(numOfThreads);
		    Counter counter=new Counter();
		    ExecutorService exec=Executors.newCachedThreadPool();
		    
		    for(int i=0;i<numOfThreads;i++)
		    	exec.execute(new Concurrency(counter,latch));
		    
		     exec.execute(new WaitingTask(latch,startTime));
		    
		 
	}
	


}
class Counter{
    final int TOTAL=10000000;
	AtomicInteger  num=new AtomicInteger(2);
	
	public int nextNum(){
		   if(num.get()<=TOTAL)
			 
			   return num.incrementAndGet();	
		
		   return 0;
			   
	}
	
}
class WaitingTask implements Runnable{
	private final CountDownLatch latch;
	private  final long startTime;
	
	public WaitingTask(CountDownLatch latch,long startTime){
		this.latch=latch;
		this.startTime=startTime;
	}

	@Override
	public void run() {
		try {
		
			latch.await();
			System.out.println("共有"+Concurrency.count+"个素数"+"用时"+(System.currentTimeMillis()-startTime));
		} catch (InterruptedException e) {
			System.out.println("等待线程被中断");
		}
	     
		
	}
}


 

 

 

 

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值