我(重新)学习C并且在我正在阅读的书中我们正在讨论数组,本书给出了一个查找前n个素数的算法;我自己是一名数学家,并且是一些技术熟练的程序员,我决定使用不同的算法(使用Eratosthenes的筛子)获得前n个素数。好吧,算法运行良好,我的工作,甚至适度大的输入,即前50,000个素数需要一点运行,但没有问题。然而,当你开始弹出一个窗口弹出一个窗口,表示程序没有响应并且需要退出时,你几乎要说80,000个素数,我确保使得在素数上的变量是无符号long long int,所以我仍然应该在他们的价值观可接受的范围内。我做了一些粗略的在线浏览,其他有大量输入问题的人收到了建议在main之外创建变量的建议,以使它们成为全局变量。我尝试了一些我可以立即放在外面的变量,但这并没有解决问题。可能我需要将我的数组isPrime或primes放在main之外?但由于我的所有工作都是主要的,所以我无法真正看到如何做到这一点。
我意识到我应该用不同的功能做到这一点,但我只是按照我的方式编写它,但是如果我将所有内容都移到单独的函数中,那么我的数组仍然不是全局的,所以我不是。确定如何解决这个问题。
我尝试将它们设置为静态或外部,尝试将它们从堆栈内存中取出,但自然不会起作用,因为它们的数组会根据输入改变大小,并随着时间的推移而变化。
代码是:
#include <math.h>
#include <stdbool.h>
#include <stdio.h>
unsigned long long int i,j;
unsigned long long int numPrimes,numPlaces;
int main(void)
{
bool DEBUG=false;
printf("How many primes would you like to generate? ");
scanf("%llu",&numPrimes);
// the nth prime is bounded by n*ln(n)+n*ln(ln(n)), for n >=6
// so we need to check that far out for the nth prime
if (numPrimes>= 6)
numPlaces = (int) numPrimes*log(numPrimes)+
numPrimes*log(log(numPrimes));
else
numPlaces = numPrimes*numPrimes;
if(DEBUG)
printf("numPlaces: %llu\n\n", numPlaces);
// we will need to check each of these for being prime
// add one so that we can just ignore starting at 0
bool isPrime[numPlaces+1];
// only need numPrimes places, since that is all we are looking for
// but numbers can and will get large
unsigned long long int primes[numPrimes];
for (i=2; i<numPlaces+1;i++)
isPrime[i] = true; // everything is prime until it isn't
i=2; // represents current prime
while (i < numPlaces + 1)
{
for (j=i+1;j<numPlaces+1;j++)
{
if (isPrime[j] && j%i ==0) // only need to check if we haven't already
{
isPrime[j] = false;// j is divisibly by i, so not prime
if(DEBUG)
{
printf("j that is not prime: %llu\n",j);
printf("i that eliminated it: %llu\n\n",i);
}//DEBUG if
}//if
}//for
// ruled out everything that was divisible by i, need to choose
// the next i now.
for (j=i+1;j<numPlaces+2;j++)// here j is just a counter
{
if (j == numPlaces +1)// this is to break out of while
{
i = j;
break;
}// if j = numPlaces+1 then we are done
else if (isPrime[j]==true)
{
i = j;
if (DEBUG)
{
printf("next prime: %llu\n\n",i);
}//DEBUG if
break;
}//else if
}// for to decide i
}//while
// now we have which are prime and which are not, now to just get
// the first numPrimes of them.
primes[0]=2;
for (i=1;i<numPrimes;i++)// i is now a counter
{
// need to determine what the ith prime is, i.e. the ith true
// entry in isPrime, 2 is taken care of
// first we determine the starting value for j
// the idea here is we only need to check odd numbers of being
// prime after two, so I don't need to check everything
if (i<3)
j=3;
else if (i % 2 ==0)
j = i+1;
else
j = i;
for (;j<numPlaces+1;j+=2)// only need to consider odd nums
{
// check for primality, but we don't care if we already knew
// it was prime
if (isPrime[j] && j>primes[i-1])
{
primes[i]=j;
break;
}//if, determined the ith prime
}//for to find the ith prime
}//for to fill in primes
// at this point we have all the primes in 'primes' and now we just
// need to print them
printf(" n\t\t prime\n");
printf("___\t\t_______\n");
for(i=0;i<numPrimes;i++)
{
printf("%llu\t\t%llu\n",i+1,primes[i]);
}//for
return 0;
}//main
我想我可以避免使用质数数组,只使用isPrime的索引,如果这会有帮助吗?任何想法都会有所帮助!
答案 0 :(得分:2)
您分配的数组是堆栈变量(很可能),并且堆栈大小有限,因此您可能会在达到特定大小阈值时覆盖重要内容,从而导致程序崩溃。尝试使用分配有malloc的动态数组来存储筛子。
答案 1 :(得分:2)
您的问题在于此处,在VLA的定义中(“可变长度数组”,而非“非常大的数组”)
bool isPrime[numPlaces+1];
当isPrime
很大时,程序在数组numPlaces
的局部变量区域中没有足够的空间。
您有两种选择:
malloc()
和朋友选项1
#include <stdio.h>
unsigned long long int i,j;
bool isPrime[5000000]; /* waste memory */
int main(void)
选项2
int main(void)
{
bool *isPrime;
// ...
printf("How many primes would you like to generate? ");
scanf("%llu",&numPrimes);
// ...
// we will need to check each of these for being prime
// add one so that we can just ignore starting at 0
isPrime = malloc(numPrimes * sizeof *isPrime);
// ... use the pointer exactly as if it was an array
// ... with the same syntax as you already have
free(isPrime);
return 0;
}