使用C中的大数字和GMP

时间:2017-10-06 18:33:08

标签: c gmp bignum

我遇到了一个代码,它会返回一个大于C可以处理的nunber的代码。我安装了GMP库,但是我在互联网上找到的所有教程都无法让它发挥作用。这是具有GMP库功能的代码。目前,我正在尝试通过阅读此网站的手册来使其发挥作用:https://gmplib.org/manual/ 程序只是崩溃,我认为这是因为我从Int函数返回一个mpz_t整数。我怎么能解决这个问题?

编辑:我编辑了Antoine所说的代码,现在我没有错误,但是当我运行它时程序崩溃。

#include <stdio.h>
#include <time.h>
#include <math.h>
#include <gmp.h>

typedef struct Vector{
int *v;
}vetor;

int nextPow2(int n);
int Multiplicacao(mpz_t r, int *x, int *y, int n);

int main(){

int n = 100;
vetor *x = malloc(sizeof(vetor));
vetor *y = malloc(sizeof(vetor));

srand( (unsigned)time(NULL) );
int i;

int c = 0;
i=0;
c = nextPow2(n);

x->v = malloc(sizeof(int)*c);
y->v = malloc(sizeof(int)*c);

for(i=0; i<c; i++){
    x->v[i] = 0;
    y->v[i] = 0;
}

int d = c-n;
i = c;
while(i>=d){
    x->v[i] = rand()%2;
    y->v[i] = rand()%2;
    i--;
}

printf("\n Vetor X\n");

for(i=0; i<c; i++){
    printf("%i", x->v[i]);
}

printf("\n Vetor Y\n");

for(i=0; i<c; i++){
    printf("%i", y->v[i]);
}

mpz_t r;
mpz_inits(r);

mpz_set(r, Multiplicacao(r, x->v, y->v, c));

printf("\n\n RESULTADO \n\n");
gmp_printf ("%Zd\n", r);
mpz_clear(r);

return 0;
}

int Multiplicacao(mpz_t r, int *x, int *y, int n){
if(n==1)
    return x[0]*y[0];
else{
    vetor *Xe = malloc(sizeof(vetor));
    vetor *Xd = malloc(sizeof(vetor));
    vetor *Ye = malloc(sizeof(vetor));
    vetor *Yd = malloc(sizeof(vetor));
    int j;
    Xe->v = malloc(sizeof(int)*n/2);
    Xd->v = malloc(sizeof(int)*n/2);
    Ye->v = malloc(sizeof(int)*n/2);
    Yd->v = malloc(sizeof(int)*n/2);

    for(j=0; j<n/2; j++){
        Xe->v[j]=x[j];
        Ye->v[j]=y[j];
    }
    int k=0;
    for(j=n/2; j<n; j++){
        Xd->v[k]=x[j];
        Yd->v[k]=y[j];
        k++;
    }

    mpz_t p1, p2, p3, p4, a, b;
    mpz_inits(p1, p2, p3, p4, a, b);

    mpz_ui_pow_ui(a, 2, n);
    mpz_ui_pow_ui(b, 2, n/2);


    mpz_set(p1, Multiplicacao(r, Xe->v, Ye->v, n/2));
    mpz_set(p2, Multiplicacao(r, Xe->v, Yd->v, n/2));
    mpz_set(p3, Multiplicacao(r, Xd->v, Ye->v, n/2));
    mpz_set(p4, Multiplicacao(r, Xd->v, Yd->v, n/2));

    mpz_mul(p1, p1, a);
    mpz_mul(p2, p2, b);
    mpz_mul(p3, p3, b);

    mpz_add(p1, p1, p2);
    mpz_add(p3, p3, p4);
    mpz_add(p1, p1, p3);

    return p1;
}
}

int nextPow2(int n)
{
if ( n <= 1 ) return n;
double d = n-1;
return 1 << ((((int*)&d)[1]>>20)-1022);
}

1 个答案:

答案 0 :(得分:1)

返回mpz_t是不好的做法。你应该把你的函数作为第一个参数mpz_t存储结果:

void func (mpz_t result, ...)
{
   ...
   mpz_set (result, ...);
}

并将其称为:

mpz_t result;
mpz_init (result);

func (result, ...);
gmp_printf ("%Zd\n", result);

mpz_clear (result);

除此之外,还要仔细阅读GMP手册。您需要阅读您使用的每个功能的完整文档。特别注意功能签名。例如,您应该使用mpz_ui_pow_ui而不是mpz_pow_ui。几乎每次在代码中使用GMP功能都是错误的。