【发布时间】:2014-11-30 10:05:10
【问题描述】:
关于我如何让这个程序为 n = 1 万亿(除了进行升级/购买新计算机)工作有什么建议吗?
错误如下:构建后,正在执行的程序(弹出命令行样式的输出窗口)然后快速关闭,出现如下错误“ProjectPrimes.exe已停止工作(Windows正在寻找这个问题的解决方案。”我怀疑这与内存问题有关,因为我第一次遇到它是在 n = 2000 万,但那是在我选择 malloc/free 'sieve' 数组之前(即,我的 'sieve' 数组是维度为 nx 1 且每个元素由 1 或 0 组成的大数组。
该程序需要大约 35 秒来运行前 3 亿个整数(16,252,325 个素数),所以没关系,但没什么了不起的。正如我所提到的,目标是能够生成低于 1 万亿的素数,所以还有很长的路要走......
如果相关,这是我的机器规格(以防目标在这台机器上不合理):2.40ghz i5、4gb RAM、64 位 Windows 7。
对于不熟悉的人的方法概述:我们使用 Sundaram 筛法。在不进入证明的情况下,我们首先使用筛函数消除整数“n”以下的所有奇数非素数:[2*(i+j+2*i*j)+1 | i
为什么素数函数会返回(指向包含数组的指针)n 以下的完整素数集?好吧,目标是能够识别(i)n以下的素数以及(ii)列出n以下的素数。这也是为什么我选择传递一个指向 n 以下素数计数的指针作为参数。
这是不那么令人兴奋的“主要”功能:
int main() {
long ceiling = 300*1000*1000;
long *numPrimes;
long *primes;
primes = primesToSS(ceiling+1, numPrimes);
printf("\n\nThere are %d primes below %d.\n\n",*numPrimes,ceiling);
free(primes);
return 0;
}
这是肉:
//n represents the ceiling, i.e., the integer below which we will generate primes
//cnt* is a pointer which will point the number of primes below n
long* primesToSS( long n, long* cnt ) {
//initialize sieve by setting all elements equal to 1 (except for 0 and 1)
long *sieve = malloc(n*sizeof(long));
initArray(sieve, n, 1);
sieve[0] = 0; sieve[1] = 0;
//eliminate all odd composite numbers
for (int i = 1; i <= n/2; ++i)
for (int j = i; j <= (n-2*i)/(2*(2*i+1)); ++j)
sieve[ 2*(i+j+2*i*j)+1 ] = 0;
//eliminate all even numbers greater than two
//and count total number of primes below n
long numPrimes = 1;
for (int i = 3; i < n; ++i) {
if (i % 2 == 0) sieve[i] = 0;
numPrimes += sieve[i];
}
*cnt = numPrimes;
//create array of primes
long *primes = malloc(numPrimes*sizeof(int));
long counter = 0;
for (int i = 0; i < n; ++i) {
if (sieve[i] == 1) {
primes[counter] = i;
counter++; }
}
free(sieve);
return primes;
}
void initArray( int* arr, int len, int n ) {
for( int i = 0; i < len; ++i) arr[i] = n; }
【问题讨论】:
-
当你的代码崩溃时会出现什么样的错误/异常?
-
请尝试提供一个最小的、可编译的、仍能显示问题的工作示例。除此之外,显然 malloc(n*sizeof(long)) 对于足够大的 n 将返回 NULL。
-
你的 sieve 数组不是标志数组吗,即零或一?为什么要使用 long 来存储单个位?
-
指针
numPrimes在传递给primesToSS()时未初始化。在该函数内部,*cnt = numPrimes;行将写入随机内存位置。 -
您应该在格式中使用
%ld来打印long值。使用 64 位long值来存储 0 或 1 值似乎也有点过分。如果您使用单个位,您将能够在筛子中存储更多值。你也可以考虑根本不用存储任何偶数;位数组可以简单地对奇数进行编码(但它允许您将 128 个数字放入当前仅获得 1 的数组的每个元素中)。
标签: c primes sieve-of-eratosthenes