我觉得很蠢。 GMP很好,这是我的疏忽。使用size_t mpz_sizeinbase (const mpz_t op, int base)
后,我意识到我用来复制结果的char数组太小了。增加它的大小解决了它。谢谢你的帮助!
我的任务是编写一个C程序,计算从第1024个元素到第1048576个元素的斐波纳契数列的元素(从2的10次幂到2的20次幂,增加2的幂)。为此,我使用GMP库来处理数字。问题是,在2的17次幂附近,数字是如此之大,即使GMP也无法处理它,这意味着我应该使用 malloc()。
这是我的 main()(我通过删除不必要的部分来修改粘贴的代码,例如写入文件和时间测量,这将用于程序的另一部分):
int main(){
int powersOfTwo[11];
char res[10000];
char *c;
c = res;
for(int i = 0; i < 11; i++){
powersOfTwo[i] = normalPower(2,i+10);
}
for(int i = 0; i < 11; i++){
fibo(c, powersOfTwo[i]);
printf("The %d th element of Fibonacci is %s\n",powersOfTwo[i],res);
memset(res, 0, sizeof res);
}
return 0;
}
现在这里是一个简单的 normalPower 功能(为了清楚起见,我们真的没有关系到这个问题):
int normalPower(int n1, int n2){
if(n2 == 0){
return 1;
}else{
int temp = n1;
for(int i = 1; i < n2; i++){
temp *= n1;
}
return temp;
}
}
现在问题是, fibo 功能:
void fibo(char *c, int n){
mpz_t *fib1;
mpz_t *fib2;
mpz_t *temp;
fib1 = (mpz_t *) malloc(101000000 * sizeof(mpz_t));
fib2 = (mpz_t *) malloc(101000000 * sizeof(mpz_t));
temp = (mpz_t *) malloc(101000000 * sizeof(mpz_t));
if (NULL == fib1 || NULL == fib2 || NULL == temp){
printf("ERROR: Out of memory\n");
}
mpz_init(*fib1);
mpz_init(*fib2);
mpz_init(*temp);
mpz_set_str(*fib1,"0",10);
mpz_set_str(*fib2,"1",10);
int i;
if(n == 0){
char *d = mpz_get_str(NULL,10,*fib1);
strcpy(c,d);
}
if(n == 1){
char *d = mpz_get_str(NULL,10,*fib2);
strcpy(c,d);
}
if(n > 1){
for(i = 1; i < n; i++){
mpz_set(*temp, *fib2);
mpz_add(*fib2, *fib1, *fib2);
mpz_set(*fib1,*temp);
}
char *d = mpz_get_str(NULL,10,*fib2);
strcpy(c,d);
}
free(fib1);
free(fib2);
free(temp);
}
最初我只使用mpz_t-s,启动它们和mpz_clear() - 最后它们没有指针和malloc(),但是这导致分段错误(核心转储)错误计算17(-ish)元素的幂的2。这是我在互联网上找到的解决方案,这几乎是我可以分配的最大数量,但仍然没有任何变化,程序在同一点停止,并显示相同的错误消息。我还尝试使用 mp_set_memory_functions()并创建自定义 mallocWrapper()并为其提供GMP,但这似乎也无效。当然,我99%肯定,这是因为我是GMP的新手并且使用 malloc()相对较新,所以我的代码可能让你们大多数人撕裂你现在的头发,我为此道歉。
基本上我的问题是:我应该如何使用 malloc()为数字获取足够的内存?
提前感谢您的所有帮助!
答案 0 :(得分:0)
这些行:
mpz_t *fib1;
mpz_t *fib2;
mpz_t *temp;
fib1 = (mpz_t *) malloc(101000000 * sizeof(mpz_t));
fib2 = (mpz_t *) malloc(101000000 * sizeof(mpz_t));
temp = (mpz_t *) malloc(101000000 * sizeof(mpz_t));
对我来说看起来非常错误(你的整个源代码闻起来很糟糕,你应该放弃它)。看来你想分配101000000个不同的bignums,我不明白为什么你需要这么多。
仔细阅读GMPlib的文档和Fibonnaci numbers的定义。你只需要几个mpz_t
(很可能你需要不到六个mpz_t
变量),而不是数百万个变量。想想编码程序之前Fibonacci 的数学定义。请注意,如果您知道 Fib(10000)和 Fib(10001)计算 Fib(10002)很容易使用GMPlib,那么您就不会需要 Fib(10000),你可以在计算后立即打印 Fib(10002)。请注意,您可以使用mpz_set指定GMP大整数。
(在考虑了数学之后,你真的应该从头开始重写你的程序你可以转储你现有的代码)
不要忘记初始化每个变量,以适当地调用mpz_init。
编译所有警告和调试信息(gcc -Wall -Wextra -g
)。 使用调试器(gdb
)和valgrind以及-fsanitize=
debugging options
据我所知,您的代码中甚至不需要对malloc
进行单显式调用(当然,内部GMPlib正在使用malloc
)。< / p>
(顺便说一句,作为一名学生,假设你的锻炼非常容易,这是有帮助的)
答案 1 :(得分:-3)
如果GMP库无法处理它,请查看使用char *和算法来处理数字。您可以轻松地执行GMP可以支持的任何操作。