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) 来提高 op1op2 次方(根据 https://gmplib.org/manual/Float-Arithmetic#index-Powering-functions-1)。

但文档似乎在 c++ 接口中只字未提。我试过使用 powpow_iupower 等名称,但其中 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