使用Malloc通过GMP处理大量数字

时间:2015-11-04 20:51:15

标签: c memory malloc dynamic-memory-allocation gmp

解决:

我觉得很蠢。 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()为数字获取足够的内存?

提前感谢您的所有帮助!

2 个答案:

答案 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可以支持的任何操作。