据说某公司面试,问了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("等待线程被中断");
}
}
}