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

问题描述 投票:3回答:2
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])

使用一个参数,返回x的自然对数(到基数e)。

使用两个参数,将x的对数返回给定的基数,计算为log(x)/ log(base)。

记录在哪里?

python floating-point logarithm
2个回答
3
投票

我终于挖到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;

        ...

我将免除剩余的源代码(检查链接),但我从中理解的是Python检查传递的参数是否为整数,如果是,则不要使用math lib(如果是int,自己做。)评论。另外:即使对于大量的int,也很容易计算出一个像样的对数,但是libm本身不能这样做 - loghelper可以

如果它是双精度数,则调用原生数学库。

从源代码注释中,我们看到Python尝试最难提供结果,即使在溢出的情况下(这里转换为双溢出,但无论如何都可以计算日志。清除异常并继续)

因此,由于log函数的python包装,Python能够计算大整数的对数(这是特定于某些函数,因为其他一些像sqrt不能这样做),并且它已被记录,但仅在源代码中,可能使Jon成为一个实施细节。


1
投票

我认为this线程是有用的,因为python现在使用长整数,避免溢出的技巧是使用_PyLong_Frexp函数,参见here和另一个公式来计算log函数,即使在尝试将long int转换为a时引发OverflowError双击,在loghelper模块查看this

© www.soinside.com 2019 - 2024. All rights reserved.