从 C 语言到 GMP 实施

From C to GMP implementation

我会问你用 c 编写的代码在 GMP 中看起来如何。我尝试写一些东西,但图书馆很难理解。我不知道如何在gmp中写操作:r = r*10 + n%10;。非常感谢您的帮助。

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <gmp.h>

long long rev(long long n)
{
    long long r = 0;
    while (n > 0)
    {
        r = r*10 + n%10;
        n = n/10;
    }
    return r;
}

bool palindrome(long long n)
{
    return (rev(n) == n);
}

void reverseAdd(long long n)
{
    long long r=0;
    while (n <= 100000000000000)
    {
        r = rev(n);
        printf("stage: %lld + %lld\n",n,r); 

        n = n + r;

        if (palindrome(n))
        {
            printf("Palindrom: %lld\n",n);
            break;
        }
        else if (n > 100000000000000)
        {
            printf("Not a palindrome\n");
        }
    }
}


int main()
{
    long long l;

    printf("Give the number to analyze:");
    scanf("%lld",&l);
    reverseAdd(l);
    return 0;
}

您需要阅读一些有关 GMP 的教程。

例如:

GMP Tutorial

Advanced GMP Tutorial

Code examples per gmp function - 我的最爱!

More GMP Examples

GMP中的一些简单函数:

mpz_t t; // this is the type of statement is needed to declare a variable
mpz_init (t); // initialization of a variable
mpz_set_ui (t, 2); // assignment of 2 to already initialized variable t
mpz_set_str (t, "1234"); // string assignment
mpz_add (t, a , b); // a + b is assigned to t, that is, t = a + b
mpz_sub (t, a, b); // subtraction
mpz_mul (t, a, b); // multiplication
gmp_printf ("% Zd ", t); // print output t

一个简单的 GMP 程序:

#include <gmp.h>
#include <stdio.h>
#include <assert.h>

int main(){

  /* The basic operation is to initialize the number */
  /* 1. Initialize the number r */
  mpz_t r;
  mpz_init(r);
  mpz_set_ui(r,15);   /*r = 15 now */

  mpz_mul_ui(r,r,10); /* r = r * 10 */

  printf (" r = ");
  mpz_out_str(stdout,10,r);
  printf ("\n");

}

r = r * 10 + n % 10; 必须分步完成:

mpz_mul_ui(r,r,10); /* r = r * 10 */

mpz_mod_ui(n,n,10); /* n = n % 10 */

mpz_add(r,r,n);     /* r = r + n */ /* r = r * 10 + n % 10 */

mpz_t变量可以作为函数参数。

引用文档: 当 mpz_t 类型的变量用作函数参数时,它实际上是按引用调用,这意味着函数对其所做的任何操作都将在调用者中对原始变量进行。当一个函数要 return 一个 mpz_t 结果时,它应该提供一个单独的参数或它设置的参数,就像 GMP 库函数所做的那样。 mpz_t 的 return 不是 return 对象,只是指向它的指针,这几乎肯定不是您想要的。所有这些也适用于 mpq_tmpf_t

这是一个接受 mpz_t 参数、进行特定计算并 return 计算结果的示例函数。

void
myfunction (mpz_t result, mpz_t param, unsigned long n)
{
  unsigned long  i;

  mpz_mul_ui (result, param, n);
  for (i = 1; i < n; i++)
    mpz_add_ui (result, result, i*7);
}

int
main (void)
{
  mpz_t  r, n;
  mpz_init (r);
  mpz_init_set_str (n, "123456", 0);

  myfunction (r, n, 20L);
  mpz_out_str (stdout, 10, r); printf ("\n");

  return 0;
}

如果 result 和 param 是同一个变量,这个例子就可以工作,就像库函数一样。但有时这很难安排,应用程序可能不想为自己的子例程操心。

示例:如何使用 GMP 反转数字:

void rev(mpz_t r, mpz_t param, mpz_t n)
{
    mpz_t nm10;        /* introduce temporary variable to hold n%10 result */ 
    mpz_init (nm10);  /* init */

    mpz_set_ui(r,0);  /* set r to 0 */

    /*    Call mpz_cmp_ui to compare op1 and op2.                        */
    /*    Return a positive value if op1 > op2, zero if op1 = op2,       */
    /*            or a negative value if op1 < op2                       */
    /*                                                                   */

    while ( mpz_cmp_ui(n,0) > 0)  /*    Call mpz_cmp_ui to compare op1 and op2 */
    {
        mpz_mul_ui(r,param,10);  /* r = r * 10  */

        mpz_mod_ui(nm10,n,10);   /* nm10 = n%10 */

        mpz_add(r,r,nm10);       /* r = r*10 + n%10; */

        mpz_div_ui(n,n,10);      /* n = n/10 */
    }
}

void reverseAdd(mpz_t n)
{
       mpz_t r;
       mpz_init (r);

       mpz_set_ui(r,0);

       mpz_out_str(stdout,10,n); printf ("  n: input value \n");

       rev(r, r, n);

       mpz_out_str(stdout,10,n);
       printf ("      n: after calculations value \n");

       mpz_out_str(stdout,10,r);
       printf ("  r: reversed value\n");

}

int main()
{
    mpz_t l;
    mpz_init (l);

    printf("Give number to analyze:");
    gmp_scanf("%Zd",l);

    reverseAdd(l);

    return 0;
}

输出:

 Give number to analyze:12345
 12345  n: input value 
 0      n: after calculations value 
 54321  r: reversed value

示例:检查给定数字是否为回文:

void rev(mpz_t r, mpz_t param, mpz_t n)
{
    mpz_t nm10;        /* introduce temporary variable to hold n%10 result */
    mpz_init (nm10);  /* init */

    mpz_set_ui(r,0);  /* set r to 0 */

    while ( mpz_cmp_ui(n,0) > 0)  /*    Call mpz_cmp_ui to compare op1 and op2 */
    {
        mpz_mul_ui(r,param,10);  /* r = r * 10  */
        mpz_mod_ui(nm10,n,10);   /* nm10 = n%10 */
        mpz_add(r,r,nm10);       /* r = r*10 + n%10; */
        mpz_div_ui(n,n,10);      /* n = n/10 */
    }
}

void analyze(mpz_t n)
{
       mpz_t r;
       mpz_init (r);

       mpz_t input;
       mpz_init (input);

       mpz_set(input, n);  /* remember the input */

       mpz_out_str(stdout,10,n);
       printf ("  n: input value \n");

       rev(r, r, n);

       mpz_out_str(stdout,10,r);
       printf ("  r: reversed value value\n");

       if (  mpz_cmp(input,r) == 0) {
            mpz_out_str(stdout,10,input);
            printf("  is a Palindrome! \n");
       }
       else{
            printf("The input number was not a Palindrome.\n");
       }
 }

int main()
{
    mpz_t l;
    mpz_init (l);

    printf("Give number to analyze: ");
    gmp_scanf("%Zd",l);

    analyze(l);

    return 0;
}

输出:

Give number to analyze: 123454321
123454321  n: input value 
123454321  r: reversed value value
123454321  is a Palindrome!

这相当于使用循环和 GMP 实现的 Marianna 的 C 代码:

void rev(mpz_t r, mpz_t n)
{
    mpz_t nm10;       /* introduce temporary variable to hold n%10 result */
    mpz_init (nm10);  /* init */

    mpz_t nn;
    mpz_init (nn);   /* init */

    mpz_set(nn, n);   /* do not use n  directly, use nn for divisions '/' */
    mpz_set_ui(r,0);  /* set r to 0! */

    while ( mpz_cmp_ui(nn,0) > 0)  /*    Call mpz_cmp_ui to compare op1 and op2 */
    {
        mpz_mul_ui(r,r,10);      /* r = r * 10  */
        mpz_mod_ui(nm10,nn,10);  /* nm10 = n%10 */
        mpz_add(r,r,nm10);       /* r = r*10 + n%10; */
        mpz_div_ui(nn,nn,10);    /* n = n/10 */
    }
}

bool palindrome(mpz_t r, mpz_t n)
{
    /* calculate the reverse number */
    rev(r, n);
    return( (mpz_cmp(r,n) == 0));
}

void analyzeAdd(mpz_t n)
{
    mpz_t r;
    mpz_init (r);

    mpz_set_ui(r,0);  /* set r to 0! */

/* loop */

    while (1)
    {
       int compare = mpz_cmp_ui(n,100000000000000);
        /*    Return a positive value if op1 > op2, zero if op1 = op2,       */
        /*    or a negative value if op1 < op2                               */

       if (compare > 0)
       {
         printf("Not a palindrome!\n");
         break; /* break the while loop */
       }

       rev(r, n); /* r is returned, n is not modified */

       printf("stage:  ");
       mpz_out_str(stdout,10,n);
       printf(" + ");
       mpz_out_str(stdout,10,r);
       printf("\n");

       /*  !!!  */
       mpz_add(n,n,r); /*   n = n + r; */


       if (palindrome(r,n))
       {
            printf("Palindrome: ");
            mpz_out_str(stdout,10,n);
            printf("\n");

            break;
        }
        else if ( mpz_cmp_ui(n,100000000000000) > 0 )
        {
            printf("Not a palindrome\n");
        }
    }/*while*/
}

int main()
{
    mpz_t l;
    mpz_init (l);

    printf("Give number to analyze: ");
    gmp_scanf("%Zd",l);

    analyzeAdd(l);

    return 0;
}

输出:

一)

Give number to analyze: 77
stage:  77 + 77
stage:  154 + 451
stage:  605 + 506
Palindrome: 1111

b)

Give number to analyze: 123456788999000 
Not a palindrome!

要打印 mpz_t 个变量,请使用 gmp_printf。 GMP 分别为 mpz_t, mpq_t and mpf_t 添加类型 ‘Z’‘Q’‘F’

The GMP types are:

F   mpf_t, float conversions
Q   mpq_t, integer conversions
M   mp_limb_t, integer conversions
N   mp_limb_t array, integer conversions
Z   mpz_t, integer conversions

gmp_printf 接受类似于标准 C printf 的格式字符串(请参阅 GNU C 库参考手册中的 Formatted Output)。

参考你的最后一个问题和你发布的程序,你可以使用gmp_printf打印l。 看下面修改的程序:

//....

int main()
{
   int k;
    mpz_t l;
    mpz_t n;
    mpz_init (n);  /* remember to init mpz variables */
    mpz_init (l);

    printf("Number to analysis: ");
    gmp_scanf("%Zd",l);

    gmp_printf ("%s the mpz number %Zd\n", "You have entered", l);

    do
    {
        mpz_set(n, l);
        analyzeAdd(n);
        mpz_add_ui(l,l,1);

     }while(false);

    gmp_printf ("%s is equal %Zd\n", "Now the n", n);

    return 0;
}

输出:

Number to analysis: 123321
You have entered the mpz number 123321
Now the n is equal 246642

我希望程序在 k > 20 时像这样显示输出,例如:

Number: 89 Number of stage: 24 Palindrome: 8813200023188

没关系,因为 k = 24。

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <math.h>
#include <gmp.h>

void rev(mpz_t r, mpz_t n)
{
    mpz_t nm10;
    mpz_init (nm10);

    mpz_t nn;
    mpz_init (nn);

    mpz_set(nn, n);
    mpz_set_ui(r,0);

    while ( mpz_cmp_ui(nn,0) > 0)
    {
        mpz_mul_ui(r,r,10);      /* r = r * 10  */
        mpz_mod_ui(nm10,nn,10);  /* nm10 = n%10 */
        mpz_add(r,r,nm10);       /* r = r*10 + n%10; */
        mpz_div_ui(nn,nn,10);    /* n = n/10 */
    }
}

bool palindrome(mpz_t r, mpz_t n)
{
    rev(r, n);
    return( (mpz_cmp(r,n) == 0));
}

void analyzeAdd(mpz_t n)
{
    mpz_t l;
    mpz_t r;
    mpz_init (r);

    mpz_set_ui(r,0);

    int k = 0;

    while (1)
    {

       k = k + 1;

       if (k > 400)
       {
         /*printf("It's not a palindrome!\n");*/
         break;
       }

       rev(r, n);

       /*printf("Krok:  ");
       mpz_out_str(stdout,10,n);
       printf(" + ");
       mpz_out_str(stdout,10,r);
       printf("\n");*/


       mpz_add(n,n,r); /*   n = n + r; */


       if (palindrome(r,n))
       {
            if (k > 20) {
            printf("Number of stage: %d ",k);
            printf("Palindrome: ");
            mpz_out_str(stdout,10,n);


            printf("\n");
            }

            break;
        }
    }
}

int main()
{
    mpz_t l;
    mpz_t n;
    mpz_init (l);

    printf("Give number: ");
    gmp_scanf("%Zd",l);

do
{
       mpz_set(n, l);
       gmp_printf("Number: %Zd \n",l);
       analyzeAdd(n);
       mpz_add_ui(l,l,1);


}while(1);



    return 0;
}