【问题标题】:why does math.log accepts big integer values?为什么 math.log 接受大整数值?
【发布时间】:2017-12-31 13:14:23
【问题描述】:
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)。

记录在哪里?

【问题讨论】:

  • "CPython 实现细节: 数学模块主要由围绕平台 C 数学库函数的薄包装器组成。" - 我认为这包括 @ 987654327@,所以这可能取决于平台,不一定是 Python 问题。
  • 你真的得到了760 ** 890 的有效结果吗?在我的机器 (osx) 上是 5903.65340562 但 wolfram alpha 说:451.131905409
  • @user1767754 尝试 890 * log(760) 以确认结果正确。不确定,你在 wolfram alpha 上发现了什么。
  • @Jean-FrançoisFabre: log(760*890) 返回“5903.653405619535318946719985244828084080638106597086949503....”。在 Wolfram Alpha 中。这似乎是正确的(用我自己的 BigInteger 的 Delphi 实现对其进行了测试)。
  • @user1767754:Wolfram Alpha 为我返回 5903.etc。你从哪里得到的 451.etc 值?

标签: python floating-point logarithm


【解决方案1】:

我终于挖到了pythonmath 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 检查传递的参数是否为整数,如果是,请不要使用数学库(如果是 int,我们自己做。) 评论。另外:即使对于大整数也很容易计算出像样的对数,但 libm 不能自己做到这一点——loghelper 可以

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

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

因此,感谢log 函数的python 包装,Python 能够计算大整数的对数(这是某些函数特有的,因为像sqrt 这样的其他一些函数不能这样做),并且它已记录在案,但是仅在源代码中,可能正如 Jon 所暗示的那样使其成为实现细节。

【讨论】:

    【解决方案2】:

    我认为this 线程很有用,因为python 现在使用长整数,避免溢出的技巧是使用_PyLong_Frexp 函数参见here 和一个替代公式来计算log 函数,即使在@ 之后也是如此尝试将 long int 转换为 Double 时会引发 987654326@,请在 this 模块中检查 loghelper

    _PyLong_Frexp 在双精度 x 和指数 e (arg~x*2**e) 的帮助下在 loghelper 内给出初始 long int arg 的近似值,然后计算 log作为log~log(x*2**e)=log(x)+log(2)*e。我缺少使用 x,e 的近似值的细节,但您可以在提供的链接中的 _PyLong_Frexp 的实现中找到它。

    【讨论】:

      猜你喜欢
      • 2015-05-29
      • 2015-10-16
      • 1970-01-01
      • 2013-05-12
      • 2017-08-11
      • 2020-09-22
      • 2021-09-30
      • 2018-03-10
      • 2022-01-15
      相关资源
      最近更新 更多