gmpxx 中mpf_class数字的幂函数



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++ 接口中没有提到它。我尝试过使用诸如powpow_iupower等名称,但没有一个被定义。

有没有办法使用 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

最新更新