从 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 的教程。
例如:
Code examples per gmp function - 我的最爱!
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_t
和 mpf_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;
}
我会问你用 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 的教程。
例如:
Code examples per gmp function - 我的最爱!
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_t
和 mpf_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;
}