gmpxx 中 mpf_class 个数字的幂函数
Power function for mpf_class numbers in gmpxx
gmp 库提供函数 void mpf_pow_ui (mpf_t rop, const mpf_t op1, unsigned long int op2)
来提高 op1
的 op2
次方(根据 https://gmplib.org/manual/Float-Arithmetic#index-Powering-functions-1)。
但文档似乎在 c++ 接口中只字未提。我试过使用 pow
、pow_iu
、power
等名称,但其中 none 已定义。
有没有办法使用 gmpxx 将浮点数提升为指数(浮点数或整数)?
gmpxx.h
包含某些数学运算的接口,例如 sqrt
(参见第 3341 行)
__GMP_DEFINE_UNARY_FUNCTION_1(mpf_t, sqrt, __gmp_sqrt_function)
其中以 caps 命名的宏依赖于名为 __gmp_expr<T, U>
的一般评估 class 模板,这反过来又允许 eval
具有混合本机和任意精度类型的表达式,这就是使 C++ GMP 接口更易于使用的原因。
但是 pow
没有这样的定义。正如 Marc Glisse 指出的那样,您必须使用 mpf_class::get_mpf_t
函数将 C++ 对象转换为 C 类型。
以下是示例代码。给它命名,比如说,test.cpp
.
#include <iostream>
#include <gmpxx.h>
using namespace std;
int main (void) {
mpf_class a = 12.3;
unsigned long int b = 123UL;
mpf_t c;
mpf_set_default_prec(100000);
mpf_init(c);
mpf_pow_ui(c, a.get_mpf_t(), b);
gmp_printf("c = %.50Ff\n", c);
return 0;
}
并用
编译
g++ test.cpp -o test -lgmpxx -lgmp
产生输出:
114374367934618002778643226182707594198913258409535335775583252201365538178632825702225459029661601216944929436371688246107986574246790.32099077871758646985223686110515186972735931183764
不幸的是,即使提高 mpf 的精度,我也不能使它与 WolframAlpha:
的答案相符超过 14 位
114374367934617190099880295228066276746218078451850229775887975052369504785666896446606568365201542169649974727730628842345343196581134.89591994282087444983721209947664895835902379607854
请注意,如果您想将任意精度浮点数提升为任意精度浮点数,您需要使用 MPFR library, which by the way is recommended 库中的函数 mpfr_pow
来处理任意精度浮点数:
New projects should consider using the GMP extension library MPFR
(http://mpfr.org) instead. MPFR provides well-defined precision and
accurate rounding, and thereby naturally extends IEEE P754.
编辑:由于 GMP 和 WolframAlpha(顺便说一下,它在内部使用 GMP)之间存在差异,我发布了 .
EDIT2:如 and in 评论中所述,存在差异是预料之中的,因为在使用 mpf_pow_ui
函数时,编译器会转换 12.3
转换为 double
,它不能用二进制精确表示,而 Mathematica 对该值使用任意精度,因此在这种特殊情况下它更准确。
EDIT3:GMP 实际上可以匹配 WolframAlpha 的结果,正如 John Bollinger 在他的 .
中所解释的
我的原始代码的问题在于使用 mpf_set_d
函数设置值 12.3
,因为它转换为 double
并因此失去精度。 John 修改了代码,改为使用 mpf_set_str
函数,转换为 C++ 后,该函数变为:
#include <iostream>
#include <gmpxx.h>
using namespace std;
int main (void) {
mpf_class a("12.3",2000);
unsigned long int b = 123UL;
mpf_t c;
mpf_set_default_prec(2000);
mpf_init(c);
mpf_pow_ui(c, a.get_mpf_t(), b);
gmp_printf("c = %.50Ff\n", c);
return 0;
}
这会输出完全正确的答案(最后一位四舍五入为“5”,因为该数字是“4”后跟“9”):
114374367934617190099880295228066276746218078451850229775887975052369504785666896446606568365201542169649974727730628842345343196581134.89591994282087444983721209947664895835902379607855
gmp 库提供函数 void mpf_pow_ui (mpf_t rop, const mpf_t op1, unsigned long int op2)
来提高 op1
的 op2
次方(根据 https://gmplib.org/manual/Float-Arithmetic#index-Powering-functions-1)。
但文档似乎在 c++ 接口中只字未提。我试过使用 pow
、pow_iu
、power
等名称,但其中 none 已定义。
有没有办法使用 gmpxx 将浮点数提升为指数(浮点数或整数)?
gmpxx.h
包含某些数学运算的接口,例如 sqrt
(参见第 3341 行)
__GMP_DEFINE_UNARY_FUNCTION_1(mpf_t, sqrt, __gmp_sqrt_function)
其中以 caps 命名的宏依赖于名为 __gmp_expr<T, U>
的一般评估 class 模板,这反过来又允许 eval
具有混合本机和任意精度类型的表达式,这就是使 C++ GMP 接口更易于使用的原因。
但是 pow
没有这样的定义。正如 Marc Glisse 指出的那样,您必须使用 mpf_class::get_mpf_t
函数将 C++ 对象转换为 C 类型。
以下是示例代码。给它命名,比如说,test.cpp
.
#include <iostream>
#include <gmpxx.h>
using namespace std;
int main (void) {
mpf_class a = 12.3;
unsigned long int b = 123UL;
mpf_t c;
mpf_set_default_prec(100000);
mpf_init(c);
mpf_pow_ui(c, a.get_mpf_t(), b);
gmp_printf("c = %.50Ff\n", c);
return 0;
}
并用
编译g++ test.cpp -o test -lgmpxx -lgmp
产生输出:
114374367934618002778643226182707594198913258409535335775583252201365538178632825702225459029661601216944929436371688246107986574246790.32099077871758646985223686110515186972735931183764
不幸的是,即使提高 mpf 的精度,我也不能使它与 WolframAlpha:
的答案相符超过 14 位114374367934617190099880295228066276746218078451850229775887975052369504785666896446606568365201542169649974727730628842345343196581134.89591994282087444983721209947664895835902379607854
请注意,如果您想将任意精度浮点数提升为任意精度浮点数,您需要使用 MPFR library, which by the way is recommended 库中的函数 mpfr_pow
来处理任意精度浮点数:
New projects should consider using the GMP extension library MPFR (http://mpfr.org) instead. MPFR provides well-defined precision and accurate rounding, and thereby naturally extends IEEE P754.
编辑:由于 GMP 和 WolframAlpha(顺便说一下,它在内部使用 GMP)之间存在差异,我发布了
EDIT2:如 mpf_pow_ui
函数时,编译器会转换 12.3
转换为 double
,它不能用二进制精确表示,而 Mathematica 对该值使用任意精度,因此在这种特殊情况下它更准确。
EDIT3:GMP 实际上可以匹配 WolframAlpha 的结果,正如 John Bollinger 在他的
我的原始代码的问题在于使用 mpf_set_d
函数设置值 12.3
,因为它转换为 double
并因此失去精度。 John 修改了代码,改为使用 mpf_set_str
函数,转换为 C++ 后,该函数变为:
#include <iostream>
#include <gmpxx.h>
using namespace std;
int main (void) {
mpf_class a("12.3",2000);
unsigned long int b = 123UL;
mpf_t c;
mpf_set_default_prec(2000);
mpf_init(c);
mpf_pow_ui(c, a.get_mpf_t(), b);
gmp_printf("c = %.50Ff\n", c);
return 0;
}
这会输出完全正确的答案(最后一位四舍五入为“5”,因为该数字是“4”后跟“9”):
114374367934617190099880295228066276746218078451850229775887975052369504785666896446606568365201542169649974727730628842345343196581134.89591994282087444983721209947664895835902379607855