我怎样才能纠正他们的工作呢?我试图根据以前的建议优化我的筛子,但在这两种情况下,代码都会中断:
递增j = j + ( i * 2)会破坏代码。
显然,我和其他人一样,也错过了一些关于优化的概念。但是一般说来,你只需要把一个素数的所有倍数标记为非素数。优化是下一步。
// prime-3
// sieve implementation
function prime3(n) {
const sieve = (new Array(n)).fill(true);
// Only iterate up to the square root n for marking
for (let i = 2; i * i <= n; i += 1) {
if (sieve[i]) {
// recommended optimization breaks the code
// j = j + ( i * 2 )
for (let j = i * i; j <= n; j = j + i) {
sieve[j] = false;
}
}
}
return makePrimes(sieve, n);
};
function makePrimes(sieve, n) {
let primes = [];
for (let i = 2; i < n; i++) {
if (sieve[i]) {
primes.push(i);
}
}
return primes;
}
console.log(prime3(100));
发布于 2020-03-15 13:54:41
你犯了一个简单的错误,没有准备你的筛子。首先,您应该消除2的所有倍数:
function makeSieve(n){
const sieve = new Array(n).fill(true);
for(let i = 2; i < sieve.length; i += 2){
sieve[i] = false;
}
}现在,当您进入标记非素数时,可以增加i * 2。
例如
3, 6, 9, 12, 15, 18, 21会变成
3, 9, 15, 21发布于 2020-03-11 14:38:34
您的优化需要应用于先去掉偶数之后(2除外)。因为当使用i==2时,可以通过i*2增量有效地跳过所有偶数。
下面是一个工作代码:
// prime-3
// sieve implementation
function prime3(n) {
let sieve = (new Array(n)).fill(true);
for (let i = 4; i < n; i+=2) {
sieve[i] = false;
}
// Only iterate up to the square root n for marking
for (let i = 2; i * i <= n; i += 1) {
if (sieve[i]) {
// now it works
// j = j + ( i * 2 )
for (let j = i * i; j <= n; j = j + i*2) {
sieve[j] = false;
}
}
}
return makePrimes(sieve, n);
};
function makePrimes(sieve, n) {
let primes = [];
for (let i = 2; i < n; i++) {
if (sieve[i]) {
primes.push(i);
}
}
return primes;
}
console.log(prime3(100));编辑
擦掉这个。进一步的测试表明,prime3比简单的筛子快3倍。
的代码虽然有效,但似乎花费了太多的技巧,并引入了额外的计算和混淆。在我的比较中,有一个简单的筛子代码执行答案中的一个。再说一次,亲吻是原则。
用原语答案317 1M来筛选1M的数字,而简单的筛子只需要241 1M。
function simpleSieve(n) {
let a = new Array(n)
let answer = []
let p
for (let i = 2; i < n; i ++) {
a[i] = i
}
for (let i = 2; i < n; i++) {
if (a[i]) {
answer.push(a[i])
p = a[i]
for(let j = p; j < n; j += p) {
a[j] = 0
}
}
}
return answer
}编辑2
用cpp和prime3进行重新测试确实比简单的筛子提高了大约3倍:
p3:
n = 100000000, t = 866717 microseconds.
n = 200000000, t = 2354425 microseconds.
n = 300000000, t = 3689165 microseconds.
n = 400000000, t = 4950224 microseconds.
n = 500000000, t = 6119779 microseconds.
n = 600000000, t = 7375925 microseconds.
n = 700000000, t = 8647293 microseconds.
n = 800000000, t = 10477116 microseconds.
n = 900000000, t = 11589894 microseconds.
n = 1000000000, t = 12806997 microseconds.
simple:
n = 100000000, t = 2316019 microseconds.
n = 200000000, t = 6063749 microseconds.
n = 300000000, t = 9783295 microseconds.
n = 400000000, t = 13315450 microseconds.
n = 500000000, t = 16640474 microseconds.
n = 600000000, t = 20282461 microseconds.
n = 700000000, t = 24219469 microseconds.
n = 800000000, t = 29203786 microseconds.
n = 900000000, t = 32965856 microseconds.
n = 1000000000, t = 37694084 microseconds.这里的代码是完整的:
void simpleSieve(int n) {
bool *a = (bool *)calloc(n, sizeof(bool));
int p;
memset(a, true, sizeof(bool) * n);
for (int i = 2; i < n; i++) {
if (a[i]) {
p = i;
for (int j = p; j < n; j += p) {
a[j] = 0;
}
}
}
free(a);
}
void prime3(int n) {
bool *sieve = (bool*)calloc(n, sizeof(bool));
sieve[2] = true;
for (int i = 3; i < n; i+=2) {
sieve[i] = true;
}
int step;
for (int i = 2; i * i <= n; i += 1) {
if (sieve[i]) {
step = i*2;
for (int j = i * i; j <= n; j = j + step) {
sieve[j] = false;
}
}
}
free(sieve);
}发布于 2020-03-11 14:15:11
实际上,优化对我来说是有效的:
// prime-3
// sieve implementation
function prime3 (n) {
const sieve = (new Array(n)).fill(true);
// Only iterate up to the square root n for marking
for (let i = 2; i * i <= n; i += 1) {
if (sieve[i]) {
// recomended optimizations break the code
// j = i * i
// j = j + ( i * 2 )
for (let j = i * i; j <= n; j = j+i) {
sieve[j] = false;
}
}
}
return makePrimes(sieve, n);
};
function makePrimes(sieve, n){
let primes = [];
for (let i = 2; i < n; i++) {
if(sieve[i]) {
primes.push(i);
}
}
return primes;
}
console.log(prime3(100));
但是你的j = j + ( i * 2 )‘优化’实际上破坏了算法。结果将包含非素数。这里有一个要检查的片段:
function prime3 (n) {
const sieve = (new Array(n)).fill(true);
// Only iterate up to the square root n for marking
for (let i = 2; i * i <= n; i += 1) {
if (sieve[i]) {
// recomended optimizations break the code
// j = i * i
// j = j + ( i * 2 )
for (let j = i * i; j <= n; j = j+(i*2)) {
sieve[j] = false;
}
}
}
return makePrimes(sieve, n);
};
function makePrimes(sieve, n){
let primes = [];
for (let i = 2; i < n; i++) {
if(sieve[i]) {
primes.push(i);
}
}
return primes;
}
console.log(prime3(100));
https://stackoverflow.com/questions/60637767
复制相似问题