【问题标题】:What's wrong with my Fibonacci sequence generator?我的斐波那契数列生成器出了什么问题?
【发布时间】:2013-04-16 00:31:51
【问题描述】:

我正在尝试解决Problem #25 on Project Euler。到目前为止,这是我所得到的:

def fibonacci(length):
    fibs = [0,1]
    while length > len(fibs):
        fibs.append(fibs[-1] + fibs[-2])        
    return fibs

fibs = fibonacci(5000)

for i in fibs:
    if len(str(i)) > 1000:
        print i

        ## The location of the number in the Fibonacci set.
        print [j for j, x in enumerate(fibs) if x == i]

我测试过的每个数字(包括一些 large ones)都会匹配,但 Project Euler 不接受我得到的答案。

我读到答案是第 4782 个数字,但我知道第一个超过 1000 位的数字是第 4787 个,

11867216745258291596767088485966669273798582100095758927648586619975930687764095025968215177396570693265703962438125699711941059562545194266075961811883693134762216371218311196004424123489176045121333888565534924242378605373120526670329845322631737678903926970677861161240351447136066048164999599442542656514905088616976279305745609791746515632977790194938965236778055329967326038544356209745856855159058933476416258769264398373862584107011986781891656652294354303384242672408623790331963965457196174228574314820977014549061641307451101774166736940218594168337251710513138183086237827524393177246011800953414994670315197696419455768988692973700193372678236023166645886460311356376355559165284374295661676047742503016358708348137445254264644759334748027290043966390891843744407845769620260120918661264249498568399416752809338209739872047617689422485537053988895817801983866648336679027270843804302586168051835624516823216354234081479331553304809262608491851078404280454207286577699580222132259241827433

Project Euler 说我尝试过的每个答案都是错误的。 (显然我还没有尝试 4782,因为那会作弊。)

我已经非常接近了,很明显出了点问题,但是什么?

【问题讨论】:

  • 您应该返回并再次阅读问题。我怀疑你只是错过了关于所问问题的一些非常微妙的东西。
  • 我认为使用math.floor(math.log10(n))+1获取数字的长度会更快

标签: python fibonacci


【解决方案1】:

您正在检查len(str(i)) > 1000,根据问题陈述,您应该检查len(str(i)) == 1000

此外,您将答案中的数字误解为斐波那契数。实际上,如果你仔细阅读,它是 fib 函数被调用的次数。您的斐波那契数 4782 是正确的。

【讨论】:

    【解决方案2】:

    根据第 25 个问题的解决者的 projecteuler 论坛,您是正确的。

    第二个以 1322 开头的大数...不是斐波那契数。

    检查 x 是否为斐波那契数的函数:

       import decimal
       def check_fib(n):
           a, b = decimal.Decimal(5*(n**2) + 4), decimal.Decimal(5*(n**2) - 4)
           return any(int(x.sqrt())==x for x in (a, b))
    

    【讨论】:

    • @johnthexiii 问题要求第一个数字包含 1000 个数字,而他的第 4782 个数字是 1000 个数字长。
    【解决方案3】:

    正如 thkang 指出的那样,伙计们的号码是错误的,见 wims 评论。你的算法有效。

    def fibonacci(length):
        fibs = [0,1]
        while length > len(fibs):
            fibs.append(fibs[-1] + fibs[-2])        
        return fibs
    
    fibs = fibonacci(5000)
    for i,n in enumerate(fibs):
    
        if len(str(n)) >= 1000:
            print i
            print n
            break
    

    这是我用来解决它的方法,我得到的答案和你一样。

    def fib():
        x, y = 0, 1
        while True:
            yield x
            x += y
            x, y = y, x
    f = fib()
    for i,n in enumerate(f):
        if len(str(n)) >= 1000:
            print i
            print n
            break
    

    【讨论】:

      【解决方案4】:

      除了问题(和问题)之外,您还可以使用Generating Functionology Fibonnaci Function 直接获取斐波那契数。

      from decimal import Decimal
      from math import sqrt
      
      #sqrt_5 = Decimal(sqrt(5))
      sqrt_5 = decimal.Decimal(5).sqrt() # As thkang suggested!
      fib = lambda n: (1/sqrt_5)*( (2/(-1+ sqrt_5))**(n+1) - (2/(-1-sqrt_5))**(n+1))
      
      for i in xrange(10000):
         if fib(i).adjusted()+1 == 1000:
            print i+1
      

      4782 是我的代码的第一个 1000 位数字。

      输出:[4782, 4783, 4784, 4785 4786]。

      关于使用生成函数http://www.math.ufl.edu/~joelar/generatingfibonacci.pdf的斐波那契公式

      【讨论】:

      • decimal.Decimal(5).sqrt() 会更准确
      【解决方案5】:

      您无需任何编程即可获得解决方案。

      我们知道,如果一个数字 m 在十进制表示中至少使用 k 个数字 log_10(m)>=k-1.

      所以基本上我们要做的就是解决不等式:

      log_10(F_n)>=999

      使用 F_n 的显式形式,您知道它是最接近 ((1+Sqrt(5))/2)^n/Sqrt(5) 的整数。我们可以将这个近似值用于 F_n。请记住,这里有一个小错误,但我们稍后会处理它。

      所以不等式变成:

      log_10(((1+Sqrt(5))/2)^n/Sqrt(5))>=999

      使用一些对数恒等式和一些排序后,它看起来像:

      n>=(999+log_10(Sqrt(5)))/log_10((1+Sqrt(5))/2)~=4781.8592

      所以我们的最终答案应该在这个附近,让我们讨论一下我之前提到的错误。 近似误差为 ((1-Sqrt(5))/2)^n/Sqrt(5)。 (1-Sqrt(5))/2~=-0.68,它的绝对值小于1,所以取幂后越来越接近0。(-0.68)^4781是一个很小的数,所以差F_n 的对数和我们使用的近似值(这些是 1000 左右的数字)之间的值甚至更小。在不精确计算的情况下,考虑到 F_n 的大小,这个差异可以完全忽略。 因此,解是最小整数n,n>=4781.8592,即4782。

      【讨论】:

        【解决方案6】:

        这个生成器提供整数,我已经测试到fib(21)

        from decimal import Decimal
        from math import sqrt
        
        while True:
        #sqrt_5 = Decimal(sqrt(5))
            sqrt_5 = Decimal(5).sqrt() # As thkang suggested!
            fib = lambda n: (1/sqrt_5)*( (2/(-1+ sqrt_5))**(n) - (2/(-1-sqrt_5))**(n))
            a=input()
            if a=="x":
                break
            d=round(fib(int(a)))
        
            print("\t"+str(d))
        

        要退出程序,只需输入x

        【讨论】:

          猜你喜欢
          • 2013-02-24
          • 2011-12-18
          • 2015-04-25
          • 1970-01-01
          • 2017-11-13
          • 1970-01-01
          • 1970-01-01
          • 2011-04-26
          • 1970-01-01
          相关资源
          最近更新 更多