如果seive(n)是1000000,我的代码可以正常工作。如果seive(n)超过10000000,它会显示我的分段错误(核心转储)。我已经阅读了有关分段错误的信息。但我无法解决这个问题。
#include <stdio.h>
#include <math.h>
using namespace std;
int seive(long int n)
{
long int A[n];
for (long int i = 2; i <= n; i += 1)
{
A[i] = i;
}
long int root = (int)sqrt(n);
for(int j = 2; j <= root; j++)
{
for(int k = 2*j; k < n ; k = k + j)
{
A[k] = 0;
}
}
int count = 0;
for (int l = 2; l < n; ++l)
{
if(A[l] != 0) count++;
}
printf("%d\n", count);
}
int main()
{
seive( 1000000);
}
答案 0 :(得分:3)
long int A [n];
这是堆栈上的数组。如果N很大,它真的很大。你的堆栈不够大,无法在这种情况下保存它,你会收到堆栈溢出错误。
解决方案包括:
动态分配内存:long int * A =(long int *)malloc(n * sizeof(long int));
动态分配内存C ++样式:long int * A = new long int [n];
使用静态分配的缓冲区(当时不在堆栈上):static long int A [n];
使其全局化:将该行向上移动3行。
答案 1 :(得分:2)
你要做的是尝试在堆栈上分配一个包含大量元素的数组(堆栈内存)
long int A[n];
通常,您可以使用
在堆上分配更大的数组int *A = new int[n]
答案 2 :(得分:2)
由于多种原因,您的自动存储空间在您的平台上超出其限制税。
首先,假设您的平台unsigned long int
为64位,每个元素不必要地比它需要的大63位。筛子通常只需要代表两个值中的一个&#34; true&#34;或&#34;假&#34;。一个bool
数组就足够了,可以对你的算法进行一些细微的调整。
其次,尽管第一项非常重要,但它并不是数组大小的主导因素。该特权属于n
,是您的任务的最高限额。您在自动存储中请求了大量空间。假设您在平台上解决了第一个和bool
的表示,只需一个字节,10000000
条目的标志数组仍然需要大约。 9.54 MB的自动存储,这不是笑话。
解决方案是动态存储,可以通过多种方式完成,其中一些方法是:
malloc(sizeof(bool)*(n+1))
(在现代C ++程序中不鼓励)new bool[n+1]]
(更好,但仍然不是很好)std::vector<bool>
容器(现在我们正在某处)采用以上内容的非常简单的抛出筛网示例如下所示。您可以使用关于偶数的优化逻辑(甚至不需要保留它们)来改进此显着,等等。但这不是重点。关键是使用动态存储,最好是具有自动生命周期的东西,std::vector<>
很适合你。
#include <iostream>
#include <vector>
#include <cmath>
#include <cstdlib>
unsigned long int sieve(unsigned long int N)
{
std::vector<bool> vec(N+1,true);
unsigned long int res = 1;
const unsigned long int SR = std::floor(std::sqrtl(static_cast<long double>(N)));
for (unsigned long int i=2; i<=SR; ++i)
{
if (vec[i])
{
++res;
for (unsigned long int j=(i << 1); j<=N; j+=i)
vec[j] = false;
}
}
for (unsigned long int i=SR+1; i<=N; ++i)
{
if (vec[i])
++res;
}
return res;
}
int main()
{
std::cout << sieve(10000000) << '\n';
return 0;
}
<强>输出强>
664580
我认为这是正确的,除非你是那种无视1
(有些人,不知道为什么)的人,在这种情况下它会被一个人拒绝。