为什么 math.log 接受大整数值?

why does math.log accepts big integer values?

from math import log,sqrt
import sys
n = 760 ** 890
print(log(n))

我得到了一个有效的结果。

现在将 log 更改为 sqrt,您将得到(如预期):

OverflowError: int too large to convert to float

所以我想 log 函数中的整数参数有一个技巧,使用整数对数,但我没有在文档中找到它。只有 this:

math.log(x[, base])

With one argument, return the natural logarithm of x (to base e).

With two arguments, return the logarithm of x to the given base, calculated as log(x)/log(base).

记录在哪里?

我认为this thread is useful since python now uses long ints, the trick to avoid overflow is the use of _PyLong_Frexp function see here and an alternative formula to compute the log function even after an OverflowError is raised when trying to convert a long int to a Double, check loghelper at this模块。

_PyLong_Frexp returns 初始 long int arg 的近似值,在 loghelper 内部借助双精度 x 和指数 e (arg~x*2**e) 而 log 计算为 log~log(x*2**e)=log(x)+log(2)*e。我遗漏了使用 x,e 进行近似的具体细节,但您可以在提供的 link 中的 _PyLong_Frexp 的实现中找到它。

我终于深入 python math lib source code 并找到了这个:

/* A decent logarithm is easy to compute even for huge ints, but libm can't
   do that by itself -- loghelper can.  func is log or log10, and name is
   "log" or "log10".  Note that overflow of the result isn't possible: an int
   can contain no more than INT_MAX * SHIFT bits, so has value certainly less
   than 2**(2**64 * 2**16) == 2**2**80, and log2 of that is 2**80, which is
   small enough to fit in an IEEE single.  log and log10 are even smaller.
   However, intermediate overflow is possible for an int if the number of bits
   in that int is larger than PY_SSIZE_T_MAX. */

static PyObject*
loghelper(PyObject* arg, double (*func)(double), const char *funcname)
{
    /* If it is int, do it ourselves. */
    if (PyLong_Check(arg)) {
        double x, result;
        Py_ssize_t e;

        ...

我会省去源代码的其余部分(检查 link),但我从中了解到 Python 检查传递的参数是否为整数,如果是,不要用math lib(如果是int就自己动手)注释。另外:一个像样的对数即使对于巨大的整数也很容易计算,但 libm 不能自己做——loghelper 可以

如果是双精度数,则调用本机数学库。

从源评论中,我们看到 Python 即使在溢出的情况下也尽最大努力提供结果(这里转换为双溢出,但可以计算无论如何记录。清除异常并继续)

因此,多亏了 log 函数的 python 包装,Python 能够计算大整数的对数(这特定于某些函数,因为其他一些函数如 sqrt 做不到),它被记录在案,但只在源代码中,可能使它成为 Jon 暗示的实现细节。