优化素数筛的速度(Java)
我正在用Java开发一种方法,它可以创建布尔数组isPrime:优化素数筛的速度(Java),java,primes,sieve-of-eratosthenes,sieve,Java,Primes,Sieve Of Eratosthenes,Sieve,我正在用Java开发一种方法,它可以创建布尔数组isPrime: boolean[] isPrime; 其中素数标记为“真”,其余标记为“假”。 当我这么做的时候,我还想数一数找到的素数: int numPrimesFound; 其基本思想是使用埃拉托斯坦筛。到目前为止,我的方法如下所示: public Sieve(final int limit) { long startTime = System.currentTimeMillis(); boolean[] isPri
boolean[] isPrime;
其中素数标记为“真”,其余标记为“假”。当我这么做的时候,我还想数一数找到的素数:
int numPrimesFound;
其基本思想是使用埃拉托斯坦筛。到目前为止,我的方法如下所示:
public Sieve(final int limit) {
long startTime = System.currentTimeMillis();
boolean[] isPrime = new boolean[limit];
this.isPrime = isPrime;
for (int i=3; i<=limit ;i+=2) {
isPrime[i] = true; //sets all even numbers to true
}
isPrime[2] = true;
numPrimesFound = 1; //special case of '2'
for (int i = 3; i * i <= limit; i += 2) {
if (isPrime[i] == true) {
for (int j = i; i * j <= limit; j += 2) {
isPrime[i * j] = false; //has a multiple ==> not a prime
numPrimesFound++; //doesn't work yet
}
}
}
long stopTime = System.currentTimeMillis(); //measuring execution time
System.out.println("Sieve: " + (stopTime - startTime) + " milliseconds.")
}
不起作用,因为筛子多次将某些非素数的值设置为“false”(例如45 bcs 3*15=45和9*5=45)那么,有没有人知道我如何重写这个程序,让它只将所有非素数设置为“false”一次 或者说,一般来说,有人能提出一些方法来加快这种方法吗?你有一个困惑:
numPrimesFound++;可以,但它必须在(int j=i;i*j的循环之外。如果使用
位集
,则可以要求它的基数
public BitSet primes(final int limit) {
long startTime = System.currentTimeMillis();
BitSet isPrime = new BitSet(limit);
// A bitSet starts all zeros but with a sieve - evrything must start prime.
isPrime.flip(0, limit);
// 0 and 1 are not prime
isPrime.clear(0);
isPrime.clear(1);
for (int i = 2; i * i <= limit; i += 2) {
if (isPrime.get(i)) {
// Remove all multiples of i.
for (int j = 2; i * j <= limit; j += 1) {
isPrime.clear(i * j);
}
}
}
long stopTime = System.currentTimeMillis(); //measuring execution time
System.out.println("Sieve: " + (stopTime - startTime) + " milliseconds.");
return isPrime;
}
public void test() {
BitSet primes = primes(50);
System.out.println("Primes: " + primes);
System.out.println("Count: " + primes.cardinality());
}
公共位集素数(最终整数限制){
long startTime=System.currentTimeMillis();
位集isPrime=新位集(限制);
//一个位集以全零开始,但有一个筛子,所有东西都必须以素数开始。
isPrime.flip(0,极限);
//0和1不是素数
isPrime.clear(0);
isPrime.clear(1);
对于(inti=2;i*i好的..这是我想到的
long startTime = System.currentTimeMillis();
int limit = 100000;
boolean[] isPrime = new boolean[limit+1];
Arrays.fill(isPrime, true);
isPrime[0] = false;
isPrime[1] = false;
int numPrimesFound = limit-1;
System.out.println("Sqrt is:" + Math.sqrt(limit));
for (int i=2; i < Math.sqrt(limit);i++) {
if (isPrime[i] == true) {
int inc = 0;
while (true) {
int j = (i*i) + (inc*i);
if( j > limit) break;
if (isPrime[j]) {
isPrime[j]= false;
numPrimesFound--;
}
inc++;
}
}
}
System.out.println("Number of Primes" + numPrimesFound);
for (int i = 2; i < limit;i++) {
if (isPrime[i])
System.out.println("Prime#:" + i);
}
long stopTime = System.currentTimeMillis(); //measuring execution time
System.out.println("Sieve: " + (stopTime - startTime) + " milliseconds.");
long startTime=System.currentTimeMillis();
整数极限=100000;
boolean[]isPrime=新的boolean[limit+1];
数组.fill(isPrime,true);
isPrime[0]=假;
isPrime[1]=假;
int numPrimesFound=limit-1;
System.out.println(“Sqrt是:”+Math.Sqrt(limit));
for(int i=2;i极限)断裂;
if(isPrime[j]){
isPrime[j]=假;
Numprimes发现--;
}
inc++;
}
}
}
System.out.println(“素数数”+numPrimesFound);
对于(int i=2;i
这是我的版本(它只计算包含输入数字可能的素数因子的集合):
import java.util.BitSet;
导入java.util.Scanner;
公共班机{
公共静态void main(字符串[]args){
扫描仪sc=新的扫描仪(System.in);
System.out.println(“输入间隔限制:”);
int limit=sc.nextInt();
int max=(int)Math.sqrt(limit);
长启动=System.currentTimeMillis();
数组中的位集=新位集(最大值);
//1不是素数
无阵列设置(0);
//2是第一个素数,所以第一步是过滤掉所有偶数
对于(int i=2;i最大值)中断;
如果(!intArray.get(currentNumber-1)){
i=当前编号;
打破
}
}
}
int b=0;
对于(int n=max-1;n>0;n--){
如果(!intArray.get(n)){
b=n+1;
打破
}
}
println(“有”+(max-intArray.cardinality())+”素数,最大的是:“+b”;
System.out.println(“总时间:+((System.currentTimeMillis()-start)/1000.0)+“s”);
}
}
要检查1亿个数字,在我的i7 3770k台式电脑上需要大约0,7秒。你对哪个结果感兴趣:素数的计数,还是素数本身?正如你所看到的,numPrimesFound
是错误的,但这与算法查找素数的速度无关。另外:你可能应该阅读。去掉t中的乘法在内部循环中,只保留一些附加内容:i*(j+2)==i*j+2*i
。为了避免初始翻转,请使用set而不是clear,然后返回limit-cardinality。您可能想删除一些行,以了解代码的功能,只是添加了一些注释。我希望现在可以更轻松地进行卸载。
final int limit=40000; // 50 000 is too big !
for (int z = i*2; z<limit; z+=i)
isPrime[z] = false; //has a multiple ==> not a prime
public BitSet primes(final int limit) {
long startTime = System.currentTimeMillis();
BitSet isPrime = new BitSet(limit);
// A bitSet starts all zeros but with a sieve - evrything must start prime.
isPrime.flip(0, limit);
// 0 and 1 are not prime
isPrime.clear(0);
isPrime.clear(1);
for (int i = 2; i * i <= limit; i += 2) {
if (isPrime.get(i)) {
// Remove all multiples of i.
for (int j = 2; i * j <= limit; j += 1) {
isPrime.clear(i * j);
}
}
}
long stopTime = System.currentTimeMillis(); //measuring execution time
System.out.println("Sieve: " + (stopTime - startTime) + " milliseconds.");
return isPrime;
}
public void test() {
BitSet primes = primes(50);
System.out.println("Primes: " + primes);
System.out.println("Count: " + primes.cardinality());
}
long startTime = System.currentTimeMillis();
int limit = 100000;
boolean[] isPrime = new boolean[limit+1];
Arrays.fill(isPrime, true);
isPrime[0] = false;
isPrime[1] = false;
int numPrimesFound = limit-1;
System.out.println("Sqrt is:" + Math.sqrt(limit));
for (int i=2; i < Math.sqrt(limit);i++) {
if (isPrime[i] == true) {
int inc = 0;
while (true) {
int j = (i*i) + (inc*i);
if( j > limit) break;
if (isPrime[j]) {
isPrime[j]= false;
numPrimesFound--;
}
inc++;
}
}
}
System.out.println("Number of Primes" + numPrimesFound);
for (int i = 2; i < limit;i++) {
if (isPrime[i])
System.out.println("Prime#:" + i);
}
long stopTime = System.currentTimeMillis(); //measuring execution time
System.out.println("Sieve: " + (stopTime - startTime) + " milliseconds.");
import java.util.BitSet;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("Enter the interval limit: ");
int limit = sc.nextInt();
int max = (int) Math.sqrt(limit);
long start = System.currentTimeMillis();
BitSet intArray = new BitSet(max);
// 1 is not prime
intArray.set(0);
// 2 is the first prime number, so the first step is to filter out all even numbers
for (int i = 2; i < limit; i+=2) {
intArray.set(i);
}
//all remaining number will be odd
int currentNumber = 3;
// i is the multiplicator and will be adjusted with the current number , in order to avoid repetition
int i = 3;
int temp;
while (currentNumber <= max) {
// flag multiple of the current prime number
while (true) {
temp = (currentNumber * i);
if (temp > max) break;
intArray.set(temp - 1);
i += 2;
}
//all non-prime numbers until now are already flagged, therefore we can find the next prime number by checking the set-status.
while (true) {
currentNumber += 2;
if (currentNumber > max) break;
if (!intArray.get(currentNumber - 1)) {
i = currentNumber;
break;
}
}
}
int b = 0;
for (int n = max -1 ; n > 0; n--){
if (!intArray.get(n)){
b = n + 1;
break;
}
}
System.out.println("There are " + (max - intArray.cardinality()) + " PRIMES and the biggest is: " + b);
System.out.println("Time in total: " + ((System.currentTimeMillis() - start) / 1000.0) + "s");
}
}