C++ 难以从大范围中筛选素数

C++ 难以从大范围中筛选素数,c++,stack,C++,Stack,您好,我正在尝试使用Eratosthenes筛来查找m到n范围内的素数,其中m>=1和n出现错误的原因 您将一个巨大的数组声明为局部变量。这就是为什么在推送main的堆栈帧时,它需要如此多的内存,以至于生成堆栈溢出异常。VisualStudio很难分析代码的预期运行时堆栈使用情况,并在需要时生成异常 使用这个紧凑的实现。此外,如果需要,可以在函数中声明bs。不要让实现变得复杂 实施 来自主筛10000;的呼叫;。在向量素数中有素数列表 注意:如注释stackoverflow中所述,这里的错误是非

您好,我正在尝试使用Eratosthenes筛来查找m到n范围内的素数,其中m>=1和n出现错误的原因 您将一个巨大的数组声明为局部变量。这就是为什么在推送main的堆栈帧时,它需要如此多的内存,以至于生成堆栈溢出异常。VisualStudio很难分析代码的预期运行时堆栈使用情况,并在需要时生成异常

使用这个紧凑的实现。此外,如果需要,可以在函数中声明bs。不要让实现变得复杂

实施 来自主筛10000;的呼叫;。在向量素数中有素数列表

注意:如注释stackoverflow中所述,这里的错误是非常意外的。您正在实现sieve,但是如果您使用biset而不是bool,它将更加有效


如果n=10^8,那么sqrtn=10^4。你的布尔数组是p[10000]。因此,有可能访问超出范围的数组。

一个简单且可读性更高的实现

typedef long long ll;
typedef vector<int> vi;
vi primes;
bitset<100000000> bs;
void sieve(ll upperbound) {         
  _sieve_size = upperbound + 1;                   
  bs.set();                                                 
  bs[0] = bs[1] = 0;                                     
  for (ll i = 2; i <= _sieve_size; i++) 
  if (bs[i]) {  //if not marked  

    for (ll j = i * i; j <= _sieve_size; j += i) //check all the multiples 
         bs[j] = 0; // they are surely not prime :-)

    primes.push_back((int)i); // this is prime 
} } 

我同意其他答案, 说你基本上应该重新开始 你关心你的代码为什么不起作用吗?你实际上没有问

我不确定你代码中的问题 已经被准确地识别了 首先,我将添加以下注释以帮助设置上下文:

void Sieve(int n) {
    int sqrtn = (int)sqrt((double)n);
    std::vector<bool> sieve(n + 1, false);
    for (int m = 2; m <= sqrtn; ++m) {
        if (!sieve[m]) {
            cout << m << " ";
            for (int k = m * m; k <= n; k += m)
                sieve[k] = true;
        }
    }
    for (int m = sqrtn; m <= n; ++m)
        if (!sieve[m])
            cout << m << " ";
}
现在让我提请您注意以下代码:

// For any int aardvark; // p[aardvark] = false means that aardvark is composite (i.e., not prime). // p[aardvark] = true means that aardvark might be prime, or maybe we just don’t know yet. 你这么说吗≤100000000虽然你的代码没有检查,所以, 大概是根≤10000,这是p[]的维度大小 上面的代码表示,对于每个整数i 不管是素数还是复合数, 根据定义,2×i、3×i、4×i等是复合的 对于c等于2×i,3×i,4×i…, 我们将p[c]=false,因为我们知道c是复合的

但仔细看看代码 它设置c=c+i,并表示p[c]=false 在检查c是否仍在范围内之前 作为p[]的有效索引 现在,如果n≤25000000,然后rootn≤5000.  如果我≤ 根,那么我≤5000,并且,只要c≤5000,然后是c+i≤10000.  但是,如果n>25000000,则rootn>5000,† 序列i=rootn;,c=i;,c=c+i; 可以将c设置为大于10000的值 然后用这个值索引到p[] 这可能就是堆栈溢出发生的地方

哦,顺便说一句;你不需要说ifp[i]==true;如果p[i]足够好

雪上加霜的是,同一块中还有第二个错误:
whilec+p[i]您得到的确切错误消息是什么?从我的快速浏览看,这个代码不是递归的,所以不期望堆栈溢出。@ OxInBox我使用VS2010,但是在IDENo.IT中说运行时错误,除了头部之外,这对我来说看起来不是非常的C++。@ OxInBox.:没有重复代码,程序也会得到堆栈溢出。首先我也这么想。但是在检查了VisualStudio之后,我找到了原因。请检查我的答案。如果需要修改/更正,请通知我。@user4684729:检查答案。您的解决方案很好,但我无法理解为什么在我的情况下增加数组大小不起作用。布尔数组就是这样吗?@user4684729 Bool是一个字节。数组是在函数本地定义的,因此它位于堆栈上。堆栈通常是1个MiB,所以bool中的1000000个元素大约是您可以达到的最大值—总是会有大量开销占用一些RAM。另一个答案使用的位集和向量位于堆栈上,但它们包含动态分配的数据,并且可以调整大小,以满足计算机或操作系统的存储限制。此外,它们是可单独访问位的数组,因此您可以将8个元素转换为一个字节。@user4581301您能给我一些链接,以便我可以进一步学习吗confused@user4684729.:以上代码更有效地使用了空间。在一个字节中,你可以放置8位,我们基本上是用这些位来确定一个元素是否为素数。嘿我发现了错误,请检查我的答案。你能告诉我为什么增加数组大小不起作用吗?首先,感谢你阅读我难看的代码。我问过@coderredoc为什么增加我的数组大小不起作用,根据你所说的,即使我在代码中使用了另一个数据结构,我也会得到错误。在此之前我会考虑更多问题,希望重新学习C++。 // For any int aardvark; // p[aardvark] = false means that aardvark is composite (i.e., not prime). // p[aardvark] = true means that aardvark might be prime, or maybe we just don’t know yet.
        int i=rootn;
        while(i--)
        {
            if(p[i]==true)
            {
                int c=i;
                do
                {
                    c=c+i;
                    p[c]=false;
                }while(c+p[i]<=rootn);
            }
        };