【问题标题】:Python mpmath not arbitrary precision?Python mpmath不是任意精度?
【发布时间】:2014-11-01 02:47:21
【问题描述】:

我正在尝试继续我之前的问题,我正在尝试使用 Benet 算法计算斐波那契数。为了以任意精度工作,我找到了mpmath。然而,实施似乎在某个值以上失败。例如第 99 个值给出:

218922995834555891712

这应该是(ref):

218922995834555169026

这是我的代码:

从 mpmath 导入 * 定义披(): 返回 (1 + sqrt(5)) / 2 定义 phi(): 返回 (1 - sqrt(5)) / 2 定义 F(n): 返回(幂(Phi(),n)-幂(phi(),n))/ sqrt(5) 开始 = 99 结束 = 100 对于范围内的 x(开始,结束): 打印(x,int(F(x)))

【问题讨论】:

    标签: python arbitrary-precision mpmath


    【解决方案1】:

    mpmath 提供任意精度(在mpmath.mp.dps 中设置),但仍然计算不准确。例如,mpmath.sqrt(5) 不准确,因此基于此的任何计算也将不准确。

    要获得sqrt(5) 的准确结果,您必须使用支持抽象计算的库,例如http://sympy.org/.

    要获得斐波那契数的准确结果,最简单的方法可能是使用仅执行整数运算的算法。例如:

    def fib(n):
      if n < 0:
        raise ValueError
    
      def fib_rec(n):
        if n == 0:
          return 0, 1
        else:
          a, b = fib_rec(n >> 1)
          c = a * ((b << 1) - a)
          d = b * b + a * a
          if n & 1:
            return d, c + d
          else:
            return c, d
    
      return fib_rec(n)[0]
    

    【讨论】:

    • 啊,我明白问题出在哪里了。有没有办法计算sqrt 所需的精度? (我需要这样计算)
    • 您的算法显然有效,对于这部分问题,我将使用它。
    • 可以计算出所需的精度,但这种计算通常比实际的sqrt(5) 和斐波那契计算要复杂得多。
    • 您可能想要运行基准测试,无论是 power(具有所需精度)还是 fib_rec 更快。我的期望是它们都是 O(log(n))。
    • 事实上它似乎是这样工作的!但是我确实需要测量执行时间并开始优化。
    【解决方案2】:

    mpmath 确实可以进行任意精度的数学运算,并且如果您使用的是任意精度数学模块而不是默认行为,它确实可以精确到任何精度(如上所述)。

    mpmath 有不止一个模块可以确定结果的准确性和速度(根据您的需要进行选择),并且默认情况下它使用 Python 浮点数,我相信您在上面看到了。

    如果你调用 mpmath 的 fib() 并设置了足够高的 mp.dps,你将得到上述正确答案。

    >>> from mpmath import mp
    >>> mp.dps = 25
    >>> mp.nprint( mp.fib( 99 ), 25 )
    218922995834555169026.0
    >>> mp.nprint( mpmath.fib( 99 ), 25 )
    218922995834555169026.0
    

    然而,如果您不使用 mp 模块,您将只能获得与 Python double 一样准确的结果。

    >>> import mpmath
    >>> mpmath.dps = 25
    >>> mpmath.nprint( mpmath.fib( 99 ), 25
    218922995834555170816.0
    

    【讨论】:

      【解决方案3】:

      实际上 mpmath 的默认精度是 15,如果您想获得高达 21 位精度的结果,我认为这还不够。

      您可以做的一件事是将精度设置为更高的值,并使用 mpmath 定义的算术函数进行加法、减法等。

          from mpmath import mp
          mp.dps = 50
          sqrt5 = mp.sqrt(5)
          def Phi():
              return 0.5*mp.fadd(1, sqrt5)
      
          def phi():
              return 0.5*mp.fsub(1, sqrt5)
      
          def F(n):
              return mp.fdiv(mp.power(Phi(), n) - mp.power(phi(), n), sqrt5)
      
          print int(F(99))
      

      这会给你

          218922995834555169026L
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多