#include
#include
#include
#include
int main(){
// void mpf_set_default_prec(mp_bitcnt_t prec)
// 将默认精度设置为至少 prec 位。所有后续调用mpf_init将使用此精度,但先前初始化的变量不受影响。
// 这个值可以按需设置,比如计算毫秒级时间,
mpf_set_default_prec(64); // 默认精度,即小数点后精确多少位
/*
* 浮点数的结构体
typedef struct
{
int _mp_prec;// mp_limb_t 的最大精度。由 mpf_init 设置,
// 由 mpf_set_prec 修改。
// _mp_d字段指向的区域包含' prec' + 1个 limb(s)。
int _mp_size;// abs(_mp_size)是最后一个字段指向的 limb(s) 数。
// 如果 _mp_size 是负数,则这就是一个负数。
mp_exp_t _mp_exp; // 以 mp_limb_t 为底的指数。
mp_limb_t *_mp_d; // 指向 limb(s) 的指针。
} __mpf_struct;
* */
mpf_t a, b, c, d, e, f, g, h;
// 第一种初始化 + 赋值的方法
mpf_init(a); // 初始化变量 a
mpf_set_ui(a, 0); // 为 a 赋值,a=0
// 第二种初始化并同时赋值的方法
mpf_init_set_ui(b, 3); // 初始化 b,并把 3 赋值给它,即 b=3
mpf_init_set_ui(c, 5); // 初始化的值为无符号整数
mpf_init_set_ui(d, 7);
mpf_init_set_ui(e, 300);
int res = mpf_init_set_str(f, "8", 10); // 正确,则返回0; 错误,则返回-1
std::cout << "-- mpf_init_set_str() [0:正确,-1:错误] res= " << res << std::endl;
mpf_init_set_str(g, "19", 10); // 初始化的值为字符串
mpf_init_set_si(h, -10); // 初始化值为有符号的数
// mpf_init()的功能 + mpf_set()的功能 = mpf_init_set()的功能
// mpf_init()的功能 + mpf_set_ui()的功能 = mpf_init_set_ui()的功能
gmp_printf("-- a= %Ff, b= %Ff, c= %Ff, d= %Ff, e= %Ff, f= %Ff, g= %Ff\n", a, b, c, d, e, f, g); // 显示初始化的变量值
mpf_add(a, b, c); // 加法
gmp_printf("-- 加法(a=b+c):\t\t%Ff\n", a); // 默认保留 6 位小数
gmp_printf("-- 加法(a=b+c)[精度 2]:%.*Ff\n", 2, a);
mpf_add(a, b, f); // 加法
gmp_printf("-- 加法(a=b+f)[精度 2]:%.*Ff\n", 2, a);
mpf_add(a, c, f); // 加法
gmp_printf("-- 加法(a=c+f)[精度 2]:%.*Ff\n", 2, a);
mpf_add(a, g, f); // 加法
// 打印结构体元素
gmp_printf("-- 加法(a=g+f)[精度 2]:\t%.*Ff,\t_mp_prec= %d, _mp_size= %d, _mp_exp= %d, _mp_d= %d\n", 2, a, a->_mp_prec, a->_mp_size, a->_mp_exp, *a->_mp_d);
mpf_sub(a, b, c); // 减法
gmp_printf("-- 减法(a=b-c):\t\t%Ff\n", a); // 默认保留 6 位小数
// 打印结构体元素
gmp_printf("-- 减法(a=b-c)[精度 2]:\t%.*Ff,\t_mp_prec= %d, _mp_size= %d, _mp_exp= %d, _mp_d= %d\n", 2, a, a->_mp_prec, a->_mp_size, a->_mp_exp, *a->_mp_d);
mpf_mul(a, b, c); // 乘法
gmp_printf("-- 乘法(a=b*c):\t\t%Ff\n", a); // 默认保留 6 位小数
// 打印结构体元素
gmp_printf("-- 乘法(a=b*c)[精度 2]:\t%.*Ff,\t_mp_prec= %d, _mp_size= %d, _mp_exp= %d, _mp_d= %d\n", 2, a, a->_mp_prec, a->_mp_size, a->_mp_exp, *a->_mp_d);
mpf_div(a, b, d); // 除法
gmp_printf("-- 除法(a=b/d):\t\t%Ff\n", a); // 默认保留 6 位小数
gmp_printf("-- 除法(a=b/d)[精度 2]:\t%.*Ff\n", 2, a);
gmp_printf("-- 除法(a=b/d)[精度 9]:\t%.*Ff\n", 9, a);
// 打印结构体元素
gmp_printf("-- 除法(a=b/d)[精度 10]:%.*Ff,\t_mp_prec=%d, _mp_size=%d, _mp_exp=%d, _mp_d=%d\n", 10, a, a->_mp_prec, a->_mp_size, a->_mp_exp, *a->_mp_d);
/**
* gmp 数据转换为字符串
* char * mpf_get_str (char *str, mp_exp_t *expptr, int base, size_t n_digits, const mpf_t op)
* str: 如果为nullptr,则函数返回转换后的值;如果为非nullptr,则此变量保存转换后的值
* expptr: 小数点的下标位置,因为转换后的数字字符串是纯数字的。
* 即:如op=3.1415926,则expptr=1;如op=314.15926,则expptr=3;如op=0.314,则expptr=0
* base: 进制,范围:2..36,使用数字和小写字母;-2 ..- 36,使用数字和大写字母;
* 37..62,使用数字,大写字母和小写字母(按重要性顺序)
* n_digits:最多生成n_digits个数字。如果 n_digits为0,则将生成该准确的最大位数。
* 当n_digits为0以获取所有有效数字时,应用程序将无法知道所需的空间,
* 在这种情况下,str应该是nullptr
* op: 被转换的数据
*/
char *word; // 保存转换完的数据
int length; // 转换完的字符串长度
mp_exp_t exponent; // 保存结果字符串
word = mpf_get_str(nullptr, &exponent, 10, 0, a);
length = strlen(word);
printf("-- mpf_get_str(): word:\texponent= %ld, length= %d, word= %s\n", exponent, length, word);
mpf_div(a, e, d); // 除法
gmp_printf("-- 除法(a=e/d)[精度 10]:%.*Ff\n", 10, a);
word = mpf_get_str(nullptr, &exponent, 10, 0, a); // 把gmp数字转为字符串
length = strlen(word);
printf("-- mpf_get_str(): word:\texponent= %ld, length= %d, word= %s\n", exponent, length, word);
mpf_pow_ui(a, b, 3); // 幂
gmp_printf("-- 幂(a=b^3)[精度 2]:%.*Ff,\t_mp_prec=%d, _mp_size=%d, _mp_exp=%d, _mp_d=%d\n", 2, a, a->_mp_prec, a->_mp_size, a->_mp_exp, *a->_mp_d);
mpf_mul_2exp(a, b, 0); // a = b * 2^0
gmp_printf("-- 2exp(a=b* 2^0)[精度 2]:%.*Ff,\t_mp_prec=%d, _mp_size=%d, _mp_exp=%d, _mp_d=%d\n", 2, a, a->_mp_prec, a->_mp_size, a->_mp_exp, *a->_mp_d);
mpf_mul_2exp(a, b, 1);
gmp_printf("-- 2exp(a=b* 2^1)[精度 2]:%.*Ff,\t_mp_prec=%d, _mp_size=%d, _mp_exp=%d, _mp_d=%d\n", 2, a, a->_mp_prec, a->_mp_size, a->_mp_exp, *a->_mp_d);
mpf_mul_2exp(a, b, 2);
gmp_printf("-- 2exp(a=b* 2^2)[精度 2]:%.*Ff,\t_mp_prec=%d, _mp_size=%d, _mp_exp=%d, _mp_d=%d\n", 2, a, a->_mp_prec, a->_mp_size, a->_mp_exp, *a->_mp_d);
mpf_mul_2exp(a, b, 3);
gmp_printf("-- 2exp(a=b* 2^3)[精度 2]:%.*Ff,\t_mp_prec=%d, _mp_size=%d, _mp_exp=%d, _mp_d=%d\n", 2, a, a->_mp_prec, a->_mp_size, a->_mp_exp, *a->_mp_d);
// 把 b 的值赋给 a
mpf_set(a, b);
gmp_printf("-- 把 b 的值赋给 a, a:%.*Ff\n", 2, a);
// 取反,把 b 取反后的值赋给 a
mpf_neg(a, b);
gmp_printf("-- 取反,把 b 取反后的值赋给 a, a:%.*Ff\n", 2, a);
// 绝对值
mpf_abs(a, a);
gmp_printf("-- 绝对值,a:%.*Ff\n", 2, a);
// 转换 gmp 数据
unsigned int ui = mpf_get_ui(b); // gmp 数据转为 ui 类型数据
printf("-- mpf_get_ui(): b: unsigned int ui= %d\n", ui);
ui = mpf_get_ui(c); // gmp 数据转为 ui 类型数据
printf("-- mpf_get_ui(): c: unsigned int ui= %d\n", ui);
// double mpf_get_d_2exp(signed long int *exp, const mpf_t op)
// https://gmplib.org/manual/Converting-Floats
signed long int exp; // 保存精度
double d_2exp = mpf_get_d_2exp(&exp, a); // a = d_2exp * 2^exp, a = d_2exp * 2^3
gmp_printf("-- mpf_get_d_2exp(): a: %Ff, exp= %d, _mp_exp= %d, d_2exp= %f\n", a, exp, a->_mp_exp, d_2exp);
d_2exp = mpf_get_d_2exp(&exp, b);
gmp_printf("-- mpf_get_d_2exp(): b: %Ff, exp= %d, _mp_exp= %d, d_2exp= %f\n", b, exp, b->_mp_exp, d_2exp);
d_2exp = mpf_get_d_2exp(&exp, c);
gmp_printf("-- mpf_get_d_2exp(): c: %Ff, exp= %d, _mp_exp= %d, d_2exp= %f\n", c, exp, c->_mp_exp, d_2exp);
/* 输出:
-- mpf_init_set_str() [0:正确,-1:错误] res= 0
-- a= 0.000000, b= 3.000000, c= 5.000000, d= 7.000000, e= 300.000000, f= 8.000000, g= 19.000000
-- 加法(a=b+c): 8.000000
-- 加法(a=b+c)[精度 2]:8.00
-- 加法(a=b+f)[精度 2]:11.00
-- 加法(a=c+f)[精度 2]:13.00
-- 加法(a=g+f)[精度 2]: 27.00, _mp_prec= 2, _mp_size= 1, _mp_exp= 1, _mp_d= 27
-- 减法(a=b-c): -2.000000
-- 减法(a=b-c)[精度 2]: -2.00, _mp_prec= 2, _mp_size= -1, _mp_exp= 1, _mp_d= 2
-- 乘法(a=b*c): 15.000000
-- 乘法(a=b*c)[精度 2]: 15.00, _mp_prec= 2, _mp_size= 1, _mp_exp= 1, _mp_d= 15
-- 除法(a=b/d): 0.428571
-- 除法(a=b/d)[精度 2]: 0.43
-- 除法(a=b/d)[精度 9]: 0.428571429
-- 除法(a=b/d)[精度 10]:0.4285714286, _mp_prec=2, _mp_size=2, _mp_exp=0, _mp_d=1840700269
-- mpf_get_str(): word: exponent= 0, length= 21, word= 428571428571428571429
-- 除法(a=e/d)[精度 10]:42.8571428571
-- mpf_get_str(): word: exponent= 2, length= 21, word= 428571428571428571429
-- 幂(a=b^3)[精度 2]:27.00, _mp_prec=2, _mp_size=1, _mp_exp=1, _mp_d=27
-- 2exp(a=b* 2^0)[精度 2]:3.00, _mp_prec=2, _mp_size=1, _mp_exp=1, _mp_d=3
-- 2exp(a=b* 2^1)[精度 2]:6.00, _mp_prec=2, _mp_size=1, _mp_exp=1, _mp_d=6
-- 2exp(a=b* 2^2)[精度 2]:12.00, _mp_prec=2, _mp_size=1, _mp_exp=1, _mp_d=12
-- 2exp(a=b* 2^3)[精度 2]:24.00, _mp_prec=2, _mp_size=1, _mp_exp=1, _mp_d=24
-- 把 b 的值赋给 a, a:3.00
-- 取反,把 b 取反后的值赋给 a, a:-3.00
-- 绝对值,a:3.00
-- mpf_get_ui(): b: unsigned int ui= 3
-- mpf_get_ui(): c: unsigned int ui= 5
-- mpf_get_d_2exp(): a: 24.000000, exp= 5, _mp_exp= 1, d_2exp= 0.750000
-- mpf_get_d_2exp(): b: 3.000000, exp= 2, _mp_exp= 1, d_2exp= 0.750000
-- mpf_get_d_2exp(): c: 5.000000, exp= 3, _mp_exp= 1, d_2exp= 0.625000
-- 用时:16 ms
总结:
1、gmp_printf() 函数打印时如果不输入精度,则默认打印精度为6
2、通过 除法精度9 和 除法精度10 可以看出默认是有四舍五入的
3、通过 exponent=0 和 exponent=2,可以看出这是小数点的下标
*/
// 释放x占用的空间。完成所有mpf_t变量后,请确保为所有变量调用此函数 。
mpf_clear(a);
mpf_clear(b);
mpf_clear(c);
mpf_clear(d);
mpf_clear(e);
mpf_clear(f);
mpf_clear(g);
return 0;
}