【问题标题】:Calculate nth term of Fibonacci sequence in Python在 Python 中计算斐波那契数列的第 n 项
【发布时间】:2013-05-27 07:14:24
【问题描述】:

以下代码是在python中使用各种测试用例t的矩阵求幂来计算第n项og斐波那契序列。但是程序给出了荒谬的输出。请告诉我我错在哪里。当我在C++中运行代码时它运行完美.

class matrix:
    def __init__(self):
        self.a=self.b=self.c=1
        self.d=0

    def mul(self,e,f):
        ret = matrix()
        ret.a=(e.a*f.a)+(e.b+f.c)
        ret.b=(e.a*f.b)+(e.b+f.d)
        ret.c=(e.c*f.a)+(e.d+f.c)
        ret.d=(e.c*f.b)+(e.d+f.d)
        return ret

    def exp(self,a,p):
        if(p==0):
            temp=matrix()
            temp.a=temp.b=temp.c=temp.d=1
            return temp
        if(p==1):
            return a
        if(p%2==0):
            return self.exp(self.mul(a,a),p/2)
        else:
            return self.mul(a,self.exp(self.mul(a,a),(p-1)/2))

    def fib(self,n):
        if (n==0):
            return 0
        if (n==1):
            return 1
        s=matrix()
        s=self.exp(s,n)
        return s.d

t=int(raw_input())
while(t>0):
    v=matrix()
    n=int(raw_input())
    print v.fib(n)
    t=t-1

【问题讨论】:

标签: python matrix fibonacci


【解决方案1】:

问题在于您的__init__ 函数。在 python 中,所谓的变量只是内存中数据的“标签”。与 C/C++ 相比,这些可以被认为是指针。当您分配self.a = self.b = self.c 时,您基本上是为内存中的相同数据分配了三个不同的名称。您在a 中所做的任何更改都将反映在bc 等中。

对于需要三个单独变量的问题,更改__init__ 函数的一种方法如下:

self.a, self.b, self.c = 1, 1, 1

或者您可以使用copycopy() 告诉 python 分配一个新的内存位置,然后将右侧的标签分配给该位置。有关更多信息,请阅读http://docs.python.org/2/library/copy.html 的官方文档。您还可以在Python Tutorial: Shallow and Deep-copy 中阅读有关此内容的简短演练@

【讨论】:

  • 一旦你知道在python中变量只是名称,你会注意到以下语句:self.b = 1self.a = self.b将分配两个不同的“变量”,因为self.b现在已经由python确定为int,并在分配int对象时创建一个新对象。再次参考 python 文档 ref 以了解何时创建新变量以及何时在分配时创建同一变量的另一个名称。
  • 原则上你是对的,但在这种特殊情况下是错误的:int 值在 Python 中是不可变的,所以 a = b = 1a, b = 1, 1 不会有任何不同的行为。可变对象会有所不同:a = b = []...
  • 谢谢先生。但是在进行上述更改后,程序仍然给出相同的输出。
  • 请参阅我上面的评论以进行澄清。在第一种情况下self.a = self.b = self.c 对象类型尚未确定,因此名称将引用与默认行为相同的变量。在self.b = 1 后跟self.a = self.b 的第二种情况下,类型已确定,因此self.a 将是一个新变量。您可以使用命令id(<object-name>) 来验证这一点
  • @KartikKhare 在您的代码中还有其他这种行为的实例。例如,在您的exp() 函数中,您再次有一个分配temp.a = temp.b = temp.c = 1。正如我在上面的评论print id(<object-name>) 中提到的那样交叉检查你在做什么。在 [pythontutor.com/] 中运行您的代码也可能是值得的。它可以让您可视化您的代码
【解决方案2】:

有几个问题,按重要性排序:

1) 你的乘法错误。注意右边有和的乘法):

def mul(self,e,f):
    ret = matrix()
    ret.a=(e.a*f.a)+(e.b*f.c)
    ret.b=(e.a*f.b)+(e.b*f.d)
    ret.c=(e.c*f.a)+(e.d*f.c)
    ret.d=(e.c*f.b)+(e.d*f.d)
    return ret

2) 在最后一行中,您执行return s.d,但您应该返回s.bs.c,否则您将获得少一个斐波那契。

3) temp.a=temp.b=temp.c=temp.d=1 行不是必需的,因为构造函数完成了工作。此外它是错误的,因为d 应该是0

4) 为什么mulexp 类函数不使用self。没有害处,但应该是@staticmethod

5) 同样,它没有害处,但您的第二个递归调用是不必要的复杂。随便写:

    return matrix.mul(a,matrix.exp(a, p-1))

【讨论】:

  • 先生,您能否建议我应该在哪里使用模数 (%),以便在非常短的时间内计算大数 (>10^7) 的斐波那契
  • @KartikKhare:请不要叫我“先生”...关于您的问题,您的模运算很好,我的建议只是更改 else: 部分,因为它是这种方式更简单(尽管等效)。无论如何,如果您想更快,您可以使用 比内公式在恒定时间内计算它。
【解决方案3】:

我不确定您是否需要对这个问题使用矩阵求幂。不幸的是,我对 Python 类还不太了解。但是,下面的代码做了问题标题想要的:找到第 n 个斐波那契数。下面我将其描述为 F_n。注意低 n 值的初始条件。

def fibN( n ):
"""
fibonacci: int -> int
Returns F_n.
Note: F_1 = 0, F_2 = 1, F_3 = 1, F_4 = 2
"""
n = abs( int( n ))
if n == 0:
    fib = 0
elif n == 1:
    fib = 1
else:
    counter = 2  
    f0 = 0
    f1 = 1
    fib = f0 + f1
    while counter <= n:
        fib = f0 + f1
        f0 = f1
        f1 = fib
        counter += 1
return fib

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-07-22
    • 1970-01-01
    • 2016-12-11
    • 1970-01-01
    • 2022-12-10
    • 2020-01-18
    • 2012-08-19
    相关资源
    最近更新 更多