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

时间:2017-12-31 13:14:24

标签: python floating-point logarithm

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)。

记录在哪里?

2 个答案:

答案 0 :(得分: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检查传递的参数是否为整数,如果是,则不要使用数学lib(如果是int,自己动手。)评论。另外:一个像样的对数很容易计算,即使对于大量的整数,但libm本身也不能这样做 - loghelper可以

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

从源代码注释中,我们发现即使在溢出的情况下,Python也会尽最大努力提供结果(这里转换为双重溢出,但无论如何都可以计算日志。清除例外并继续

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

答案 1 :(得分:1)

我认为this线程很有用,因为python现在使用长整数,避免溢出的技巧是使用_PyLong_Frexp函数看here和另一个公式来计算{{} 1}}函数即使在尝试将long int转换为Double时引发log,也请检查this模块上的OverflowError