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
等名称,但没有一个被定义。
有没有办法使用 gmpxx 将浮点数提高到指数(浮点数或整数)?
gmpxx.h
包含一些数学运算(如sqrt
)的接口(参见第 3341 行)
__GMP_DEFINE_UNARY_FUNCTION_1(mpf_t, sqrt, __gmp_sqrt_function)
其中,大写字母命名的宏依赖于名为__gmp_expr<T, U>
的通用评估类模板,这反过来又允许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 = %.50Ffn", c);
return 0;
}
并编译
g++ test.cpp -o test -lgmpxx -lgmp
这会产生输出:
114374367934618002778643226182707594198913258409535335775583252201365538178632825702225459029661601216944929436371688246107986574246790.32099077871758646985223686110515186972735931183764
不幸的是,即使提高了强积金精度,我也无法使它与 WolframAlpha 的答案超过 14 位数字一致:
114374367934617190099880295228066276746218078451850229775887975052369504785666896446606568365201542169649974727730628842345343196581134.89591994282087444983721209947664895835902379607854
请注意,如果要将任意精度浮点数提升为任意精度浮点数,则需要使用 MPFR 库中的函数mpfr_pow
,顺便说一下,建议使用该函数库来处理任意精度浮点数:
新项目应考虑使用 GMP 扩展库 MPFR (http://mpfr.org)相反。MPFR 提供明确定义的精度和 精确舍入,从而自然扩展IEEE P754。
编辑:由于GMP和WolframAlpha之间的差异(顺便说一下,它在内部使用GMP),我发布了这个问题。
EDIT2:如本文和本评论中所述,差异是意料之中的,因为当使用mpf_pow_ui
函数时,编译器将12.3
转换为double
,这在二进制中不能完全表示,而 Mathematica 对该值使用任意精度,因此在这种特殊情况下更准确。
编辑3: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 = %.50Ffn", c);
return 0;
}
这将输出完全正确的答案(最后一个数字四舍五入为"5",因为该数字是"4"后跟"9"):
114374367934617190099880295228066276746218078451850229775887975052369504785666896446606568365201542169649974727730628842345343196581134.89591994282087444983721209947664895835902379607855