我希望通过筛选高达100,000,000来生成质数,但声明此范围的bool数组会导致我的程序崩溃。 这是我的代码:
long long i,j,n;
bool prime[100000000+1];
prime[1]=prime[0]=false;
for(i=2;i<=100000000;i++){
prime[i]=true;
}
for(i=2;i<=100000000;i++){
if(prime[i]==false){
continue;
}
for(j=i*2;j<=100000000;j+=i){
prime[j]=false;
}
}
我该如何解决这个问题?
答案 0 :(得分:3)
数组素数的大小为100 MB,并且不允许在堆栈上声明如此大的数组。尝试将数组放在全局范围内以将其分配到堆上,或者使用new(in C++
)或malloc(in C
)分配它。在那之后不要忘记释放记忆!
答案 1 :(得分:2)
变量可以存储在三个不同的存储区中:静态存储器,自动存储器,动态存储器。自动内存(非静态局部变量)的大小有限,你越过它,这会使程序崩溃。另一种方法是将数组标记为静态,这将把数组放在静态存储中,或使用动态内存。
因为这是标记C ++ ...
使用易于使用的std::vector
并使用动态内存。
#include <vector>
//...
//...
long long i,j,n;
std::vector<bool> prime(100000000+1, true);
prime[1]=prime[0]=false;
for(i=2;i<=100000000;i++){
if(prime[i]==false){
continue;
}
for(j=i*2;j<=100000000;j+=i){
prime[j]=false;
}
}
std::vector<bool>
使用“比特效率”表示,这意味着这里的std :: vector将比传统数组少8个 1 次内存。
std::bitset
类似,但大小不变,你必须将其标记为静态以避免在自动内存中占用空间。
你没有问过,但Erastostenes Sieve并不是计算大量素数的最快算法。似乎Sieve of Atkin更快并且使用更少的内存。
1 - 当你的系统有8位字节时。
答案 2 :(得分:1)
你应该不制作一个这样大小的整体筛子。相反,使用分段的Eratosthenes筛子在连续的段中进行筛分。在第一段,计算该段内每个筛分素数的最小倍数,然后以正常方式将筛选质数的倍数标记为复合;当所有筛选质数都被使用时,该段中剩余的未标记数字是素数。然后,对于下一个段,每个筛分素数的最小倍数是结束前一个段中筛分的倍数,因此筛分一直持续到完成。
考虑从20到200的段中筛选100到200的例子; 5个筛分质数分别为3,5,7,11和13.在100到120的第一个段中,比特阵有10个槽,槽0对应101,槽 k 对应100 + 2 * k * + 1,插槽9对应119.段中3的最小倍数为105,对应插槽2;时隙2 + 3 = 5和5 + 3 = 8也是3的倍数.5的最小倍数在时隙2是105,而时隙2 + 5 = 7也是5的倍数.7的最小倍数是105在插槽2处,插槽2 + 7 = 9也是7的倍数。依此类推。
函数primes
接受参数 lo , hi 和 delta ; lo 和 hi 必须是偶数, lo &lt; hi , lo 必须大于 hi 的平方根。段大小是 delta 的两倍。长度为 m 的数组 ps 包含的筛选素数小于 hi 的平方根,其中2被删除,因为偶数被忽略,由正常的Eratosthenes筛。数组 qs 包含相应筛分素数的当前片段中最小倍数的筛子比特阵列的偏移量。在每个段之后, lo 前进两次 delta ,因此对应于 sieve的索引 i 的数字比特阵是 lo + 2 i + 1。
function primes(lo, hi, delta)
sieve := makeArray(0..delta-1)
ps := tail(primes(sqrt(hi)))
m := length(ps)
qs := makeArray(0..m-1)
for i from 0 to m-1
qs[i] := (-1/2 * (lo + ps[i] + 1)) % ps[i]
while lo < hi
for i from 0 to delta-1
sieve[i] := True
for i from 0 to m-1
for j from qs[i] to delta step ps[i]
sieve[j] := False
qs[i] := (qs[i] - delta) % ps[i]
for i from 0 to delta-1
t := lo + 2*i + 1
if sieve[i] and t < hi
output t
lo := lo + 2*delta
对于上面给出的样本,这被称为primes(100, 200, 10)
。在上面给出的示例中,qs
最初为[2,2,2,10,8],对应于最小的倍数105,105,105,121和117,并且针对第二段重置为[1, 2,6,0,11],对应于最小的倍数123,125,133,121和143。
delta 的价值至关重要;为了速度,你应该使 delta 尽可能大,以便它适合高速缓冲存储器。使用您的语言库来进行比特阵列,这样您只需为每个筛选位置取一个位。如果您需要一个简单的Eratosthenes筛子来计算筛分质数,这是我最喜欢的:
function primes(n)
sieve := makeArray(2..n, True)
for p from 2 to n step 1
if sieve(p)
output p
for i from p * p to n step p
sieve[i] := False
您可以在my blog看到更多涉及素数的算法。