10

GMP库中是否实现了任何对数函数?

4

4 回答 4

6

我知道你没有问如何实现它,但是......

您可以使用对数的属性实现一个粗略的:http: //gnumbers.blogspot.com.au/2011/10/logarithm-of-large-number-it-is-not.html

以及 GMP 库的内部结构:https ://gmplib.org/manual/Integer-Internals.html

(编辑:基本上你只使用 GMP 表示的最重要的“数字”,因为表示的基数 B^N大得多B^{N-1}

这是我对 Rationals 的实现。

    double LogE(mpq_t m_op)
    {
        // log(a/b) = log(a) - log(b)
        // And if a is represented in base B as:
        // a = a_N B^N + a_{N-1} B^{N-1} + ... + a_0
        // => log(a) \approx log(a_N B^N)
        // = log(a_N) + N log(B)
        // where B is the base; ie: ULONG_MAX

        static double logB = log(ULONG_MAX);

        // Undefined logs (should probably return NAN in second case?)
        if (mpz_get_ui(mpq_numref(m_op)) == 0 || mpz_sgn(mpq_numref(m_op)) < 0)
            return -INFINITY;               

        // Log of numerator
        double lognum = log(mpq_numref(m_op)->_mp_d[abs(mpq_numref(m_op)->_mp_size) - 1]);
        lognum += (abs(mpq_numref(m_op)->_mp_size)-1) * logB;

        // Subtract log of denominator, if it exists
        if (abs(mpq_denref(m_op)->_mp_size) > 0)
        {
            lognum -= log(mpq_denref(m_op)->_mp_d[abs(mpq_denref(m_op)->_mp_size)-1]);
            lognum -= (abs(mpq_denref(m_op)->_mp_size)-1) * logB;
        }
        return lognum;
    }

(很久以后编辑)5年后回到这个,我只是觉得log(a) = N log(B) + log(a_N)即使在本机浮点实现中也出现了核心概念很酷,这里是 ia64 的 glibc 遇到这个问题后我再次使用它

于 2014-10-03T08:04:53.103 回答
5

不,GMP中没有这样的功能。仅在 MPFR 中。

于 2012-07-11T12:16:43.347 回答
3

这是: https ://github.com/linas/anant

提供 gnu mp 实数和复数对数、exp、sine、cosine、gamma、arctan、sqrt、polylogarithm Riemann and Hurwitz zeta、confluent hypergeometric、topologists sine 等。

于 2016-10-19T04:17:14.850 回答
2

下面的方法使用了mpz_get_d_2exp并且是从gmp R 包中获得的。它可以biginteger_log在文件中的函数下找到bigintegerR.cc(您首先必须下载源代码(即tar文件))。你也可以在这里看到它:biginteger_log

// Adapted for general use from the original biginteger_log
// xi = di * 2 ^ ex  ==> log(xi) = log(di) + ex * log(2)

double biginteger_log_modified(mpz_t x) {
    signed long int ex;
    const double di = mpz_get_d_2exp(&ex, x);
    return log(di) + log(2) * (double) ex;
}

当然,上述方法可以修改为使用对数的性质(例如改变底数公式)返回任意底数的对数。

于 2020-03-23T19:31:47.077 回答