152

私はもともとプログラムを間違ってコーディングしていました。範囲内のフィボナッチ数を返す代わりに (つまり、startNumber 1、endNumber 20 は 1 と 20 の間の数値のみを指定する必要があります)、範囲内のすべてのフィボナッチ数を表示するプログラムを作成しました (つまり、startNumber 1、endNumber 20表示 = 最初の 20 個のフィボナッチ数)。私は確実なコードを持っていると思いました。また、なぜこれが起こっているのかわかりません。

startNumber = int(raw_input("Enter the start number here "))
endNumber = int(raw_input("Enter the end number here "))

def fib(n):
    if n < 2:
        return n
    return fib(n-2) + fib(n-1)

print map(fib, range(startNumber, endNumber))

誰かが私のパートII(重複のために閉鎖された - https://stackoverflow.com/questions/504193/how-to-write-the-fibonacci-sequence-in-python-part-ii)で私が指摘したwhile ループを使用してジェネレーターに startNumber と endNumber を渡す必要があります。誰かがこれを行う方法を教えてもらえますか? どんな助けでも大歓迎です。


私は学習中のプログラマーで、ちょっとしたごちゃ混ぜに出くわしました。ユーザーが入力した開始番号と終了番号によってフィボナッチ数列を計算して表示するプログラムを作成するように求められました (つまり、startNumber = 20 endNumber = 100 で、その範囲内の数値のみが表示されます)。秘訣は、それを包括的に使用することです(Pythonで行う方法がわかりませんか?-これは、包括的範囲を使用することを意味すると思いますか?)。

私がこれまでに持っているのは、実際のコーディングではなく、次のとおりです。

  • Fib シーケンス式を無限に書き込む
  • Fib シーケンスからのみ startNumber から endNumber までを表示します。

どこから始めたらいいのかわからないので、これを書く方法についてのアイデアや洞察を求めています。私は Fib シーケンスのフォーラムも作成しようとしましたが、それについても迷っています。

4

47 に答える 47

274

ウィキペディアwolframには、フィボナッチ数列に関する多くの情報があります。あなたが必要とするよりもはるかに多く。とにかく、これらのリソースを使用して必要なものを (可能であれば迅速に) 見つける方法を学ぶことは良いことです。

Fib シーケンス式を無限に書き込む

数学では、再帰的な形で与えられます:

ウィキペディアのフィボナッチ

プログラミングでは、無限は存在しません。数学形式を言語に直接変換する再帰形式を使用できます。たとえば、Python では次のようになります。

def F(n):
    if n == 0: return 0
    elif n == 1: return 1
    else: return F(n-1)+F(n-2)

お気に入りの言語で試してみてください。n が大きくなるにつれて、この形式は多くの時間を必要とすることがわかります。実際、これは時間的には O(2 n ) です。

私があなたにリンクしたサイトに行くと、これが表示されます(wolframで):

フィボナッチ方程式

これは、Python で実装するのが非常に簡単で、非常に高速に計算できます。

from math import sqrt
def F(n):
    return ((1+sqrt(5))**n-(1-sqrt(5))**n)/(2**n*sqrt(5))

それを行う別の方法は、定義に従うことです(ウィキペディアから):

数列の最初の数は 0、2 番目の数は 1 で、後続の各数は数列自体の前の 2 つの数の合計に等しく、数列 0、1、1、2、3、5、8 になります。など

あなたの言語がイテレータをサポートしている場合、次のようなことができます:

def F():
    a,b = 0,1
    while True:
        yield a
        a, b = b, a + b

Fib シーケンスからのみ startNumber から endNumber までを表示します。

フィボナッチ数を生成する方法がわかったら、数を循環させて、与えられた条件を検証するかどうかを確認するだけです。

ここで、フィボナッチ数列の n 番目の項を返す af(n) を作成したとします ( sqrt(5) のものと同様)。

ほとんどの言語では、次のようなことができます。

def SubFib(startNumber, endNumber):
    n = 0
    cur = f(n)
    while cur <= endNumber:
        if startNumber <= cur:
            print cur
        n += 1
        cur = f(n)

Python では、イテレータ形式を使用して次のようにします。

def SubFib(startNumber, endNumber):
    for cur in F():
        if cur > endNumber: return
        if cur >= startNumber:
            yield cur

for i in SubFib(10, 200):
    print i

私のヒントは、必要なものを読むことを学ぶことです。Project Euler (Google で検索してください) は、その方法を教えてくれます:P がんばって、楽しんでください!

于 2009-01-31T18:01:14.377 に答える
78

フィボナッチ数列の効率的な Pythonic ジェネレーター

このシーケンスの最短の Pythonic 世代を取得しようとしているときにこの質問を見つけました (後で、Python Enhancement Proposalで同様のものを見たことに気づきました)。近くなりますが、まだエレガントではありません)、読者の理解に役立つと思うので、最初の反復を説明するコメントをここに示します。

def fib():
    a, b = 0, 1
    while True:            # First iteration:
        yield a            # yield 0 to start with and then
        a, b = b, a + b    # a will now be 1, and b will also be 1, (0 + 1)

と使用法:

for index, fibonacci_number in zip(range(10), fib()):
     print('{i:3}: {f:3}'.format(i=index, f=fibonacci_number))

プリント:

  0:   0
  1:   1
  2:   1
  3:   2
  4:   3
  5:   5
  6:   8
  7:  13
  8:  21
  9:  34
 10:  55

(帰属の目的で、私は最近、モジュールの Python ドキュメントで同様の実装aに気付きました。変数とを使用していてもb、この回答を書く前に見たことを思い出しました。しかし、この回答は言語のより良い使用法を示していると思います。)

再帰的に定義された実装

Online Encyclopedia of Integer Sequencesは、フィボナッチ数列を次のように再帰的に定義しています。

F(n) = F(n-1) + F(n-2) (F(0) = 0 および F(1) = 1)

これを Python で再帰的に簡潔に定義するには、次のようにします。

def rec_fib(n):
    '''inefficient recursive function as defined, returns Fibonacci number'''
    if n > 1:
        return rec_fib(n-1) + rec_fib(n-2)
    return n

しかし、この数学的定義の正確な表現は、30 をはるかに超える数に対しては非常に非効率的です。以下を使用して、どれだけ遅いかを示すことができます。

for i in range(40):
    print(i, rec_fib(i))

効率化のためのメモ化された再帰

速度を向上させるためにメモ化することができます (この例では、関数が呼び出されるたびにデフォルトのキーワード引数が同じオブジェクトであるという事実を利用していますが、通常は、まさにこの理由で変更可能なデフォルト引数を使用しません):

def mem_fib(n, _cache={}):
    '''efficiently memoized recursive function, returns a Fibonacci number'''
    if n in _cache:
        return _cache[n]
    elif n > 1:
        return _cache.setdefault(n, mem_fib(n-1) + mem_fib(n-2))
    return n

メモ化されたバージョンの方がはるかに高速であり、コーヒーを飲みに起きようと考える前に、最大再帰深度をすぐに超えてしまうことがわかります。これを行うことで、どれだけ高速かを視覚的に確認できます。

for i in range(40):
    print(i, mem_fib(i))

(以下のようにすればよいように思えるかもしれませんが、setdefault が呼び出される前にキャッシュ自体が呼び出されるため、実際にはキャッシュを利用できません。)

def mem_fib(n, _cache={}):
    '''don't do this'''
    if n > 1:  
        return _cache.setdefault(n, mem_fib(n-1) + mem_fib(n-2))
    return n

再帰的に定義されたジェネレーター:

Haskell を学んでいると、Haskell でのこの実装に出くわしました。

fib@(0:tfib) = 0:1: zipWith (+) fib tfib

現時点でPythonでこれに到達できると思う最も近いものは次のとおりです。

from itertools import tee

def fib():
    yield 0
    yield 1
    # tee required, else with two fib()'s algorithm becomes quadratic
    f, tf = tee(fib()) 
    next(tf)
    for a, b in zip(f, tf):
        yield a + b

これはそれを示しています:

[f for _, f in zip(range(999), fib())]

ただし、再帰制限までしか行けません。通常は 1000 ですが、Haskell のバージョンは数億に達する可能性がありますが、これにはラップトップの 8 GB のメモリがすべて使用されます。

> length $ take 100000000 fib 
100000000

n 番目のフィボナッチ数を取得するために反復子を使用する

コメント投稿者は次のように尋ねます。

イテレータに基づく Fib() 関数に関する質問: n 番目、たとえば 10 番目の fib 番号を取得したい場合はどうしますか?

itertools のドキュメントには、このためのレシピがあります。

from itertools import islice

def nth(iterable, n, default=None):
    "Returns the nth item or a default value"
    return next(islice(iterable, n, None), default)

そしていま:

>>> nth(fib(), 10)
55
于 2014-07-20T02:24:24.543 に答える
13

時間の複雑さ :

キャッシング機能は、フィボナッチ数列の再帰ツリーの繰り返しを排除することにより、フィボナッチ数列を計算する通常の方法をO(2^n)からO(n)に削減します。

ここに画像の説明を入力

コード :

import sys

table = [0]*1000

def FastFib(n):
    if n<=1:
        return n
    else:
        if(table[n-1]==0):
            table[n-1] = FastFib(n-1)
        if(table[n-2]==0):
            table[n-2] = FastFib(n-2)
        table[n] = table[n-1] + table[n-2]
        return table[n]

def main():
    print('Enter a number : ')
    num = int(sys.stdin.readline())
    print(FastFib(num))

if __name__=='__main__':
    main()
于 2014-09-30T10:14:59.723 に答える
10

O(log n) の基本的な算術演算を使用すると、これは非常に効率的です。

def fib(n):
    return pow(2 << n, n + 1, (4 << 2*n) - (2 << n) - 1) % (2 << n)

これは O(1) の基本的な算術演算を使用しますが、中間結果のサイズが大きいため、まったく効率的ではありません。

def fib(n):
    return (4 << n*(3+n)) // ((4 << 2*n) - (2 << n) - 1) & ((2 << n) - 1)

これは、二乗による累乗を使用して、多項式環 Z[X] / (X^2 - X - 1) で X^n を計算します。その計算の結果は多項式 Fib(n)X + Fib(n-1) であり、そこから n 番目のフィボナッチ数を読み取ることができます。

繰り返しますが、これは O(log n) 算術演算を使用し、非常に効率的です。

def mul(a, b):
        return a[0]*b[1]+a[1]*b[0]+a[0]*b[0], a[0]*b[0]+a[1]*b[1]

def fib(n):
        x, r = (1, 0), (0, 1)
        while n:
                if n & 1: r = mul(r, x)
                x = mul(x, x)
                n >>= 1
        return r[0]
于 2016-06-02T07:47:03.287 に答える
6

フィボナッチ数列を出力する正規の Python コード:

a,b=1,1
while True:
  print a,
  a,b=b,a+b       # Could also use b=a+b;a=b-a

問題「1000 桁を超える最初のフィボナッチ数を表示」の場合:

a,b=1,1
i=1
while len(str(a))<=1000:
  i=i+1
  a,b=b,a+b

print i,len(str(a)),a
于 2014-02-06T15:39:57.527 に答える
3

フィボナッチ数列: 1, 1, 2, 3, 5, 8, ....

つまり、、、、、。f(1) = 1_ f(2) = 1_ f(3) = 2_...f(n) = f(n-1) + f(n-2)

私のお気に入りの実装 (最も単純でありながら、他の実装と比較して非常に高速です) は次のとおりです。

def fibonacci(n):
    a, b = 0, 1
    for _ in range(1, n):
        a, b = b, a + b
    return b

テスト

>>> [fibonacci(i) for i in range(1, 10)]
[1, 1, 2, 3, 5, 8, 13, 21, 34]

タイミング

>>> %%time
>>> fibonacci(100**3)
CPU times: user 9.65 s, sys: 9.44 ms, total: 9.66 s
Wall time: 9.66 s

編集:この実装の視覚化の例。

于 2016-03-14T09:33:26.497 に答える
3

再帰を使用します。

def fib(n):
    if n == 0:
        return 0
    elif n == 1:
        return 1
    else:
        return fib(n-1) + fib(n-2)
x=input('which fibonnaci do you want?')
print fib(x)
于 2013-04-11T13:53:43.343 に答える
2

それを行う別の方法:

a,n=[0,1],10
map(lambda i: reduce(lambda x,y: a.append(x+y),a[-2:]),range(n-2))

'a' にリストを代入し、'n' に整数を代入する Map と reduce は、Python で最も強力な 3 つの関数のうちの 2 つです。ここで map は、「n-2」回反復するためだけに使用されます。a[-2:] は、配列の最後の 2 つの要素を取得します。a.append(x+y) は最後の 2 つの要素を追加し、配列に追加します

于 2014-02-07T06:05:27.013 に答える
1

これらはすべて、必要以上に複雑に見えます。私のコードは非常にシンプルで高速です。

def fibonacci(x):

    List = []
    f = 1
    List.append(f)
    List.append(f) #because the fibonacci sequence has two 1's at first
    while f<=x:
        f = List[-1] + List[-2]   #says that f = the sum of the last two f's in the series
        List.append(f)
    else:
        List.remove(List[-1])  #because the code lists the fibonacci number one past x. Not necessary, but defines the code better
        for i in range(0, len(List)):
        print List[i]  #prints it in series form instead of list form. Also not necessary
于 2014-02-02T04:59:00.810 に答える
1
import time
start_time = time.time()



#recursive solution
def fib(x, y, upperLimit):
    return [x] + fib(y, (x+y), upperLimit) if x < upperLimit else [x]

#To test :

print(fib(0,1,40000000000000))
print("run time: " + str(time.time() - start_time))

結果

[0、1、1、2、3、5、8、13、21、34、55、89、144、233、377、610、987、1597、2584、4181、6765、10946、17711、28657、46368 , 75025, 121393, 196418, 317811, 514229, 832040, 1346269, 2178309, 3524578, 5702887, 9227465, 14930352, 24157817, 39088169, 63245986, 102334155, 165580141, 267914296, 433494437, 701408733, 1134903170, 1836311903, 2971215073, 4807526976, 7778742049 , 12586269025, 20365011074, 32951280099, 53316291173, 86267571272, 139583862445, 225851433717, 365435296162, 591286729879, 956722026041, 1548008755920, 2504730781961, 4052739537881, 6557470319842, 10610209857723, 17167680177565, 27777890035288, 44945570212853]

実行時間: 0.04298138618469238

于 2016-11-22T04:39:18.090 に答える
1

おもしろいことに、Python 3.8 以降では、リスト内包表記で代入式(セイウチ演算子とも呼ばれます) を使用できます。たとえば、次のようになります。

>>> a, b = 0, 1
>>> [a, b] + [b := a + (a := b) for _ in range(8)]  # first 10 Fibonacci numbers
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

代入式を使用すると、値を変数に代入して、同じ式返すことができます。したがって、式

b := a + (a := b)

を実行するのと同等です

a, b = b, a + b

の値を返しますb

于 2019-11-30T16:24:51.300 に答える
0

多分これが役立つでしょう

def fibo(n):
    result = []
    a, b = 0, 1
    while b < n:
            result.append(b)
            a, b = b, b + a
    return result
于 2014-03-07T19:11:55.797 に答える
0

メモ化がフィボナッチ数列でどのように機能するかについてのより詳細な説明。

# Fibonacci sequence Memoization

fib_cache = {0:0, 1:1}

def fibonacci(n):
    if n < 0:
        return -1
    if fib_cache.has_key(n):
        print "Fibonacci sequence for %d = %d cached" % (n, fib_cache[n])
        return fib_cache[n]
    else:
        fib_cache[n] = fibonacci(n - 1) + fibonacci(n - 2)
    return fib_cache[n]

if __name__ == "__main__":
    print fibonacci(6)
    print fib_cache
    # fibonacci(7) reuses fibonacci(6) and fibonacci(5)
    print fibonacci(7)
    print fib_cache
于 2015-12-17T06:47:27.117 に答える
0
def fib(x, y, n):
    if n < 1: 
        return x, y, n
    else: 
        return fib(y, x + y, n - 1)

print fib(0, 1, 4)
(3, 5, 0)

#
def fib(x, y, n):
    if n > 1:
        for item in fib(y, x + y, n - 1):
            yield item
    yield x, y, n

f = fib(0, 1, 12)
f.next()
(89, 144, 1)
f.next()[0]
55
于 2013-11-24T01:09:50.820 に答える
0
def fib(lowerbound, upperbound):
    x = 0
    y = 1
    while x <= upperbound:
        if (x >= lowerbound):
            yield x
        x, y = y, x + y

startNumber = 10
endNumber = 100
for fib_sequence in fib(startNumber, endNumber):
    print "And the next number is... %d!" % fib_sequence
于 2015-11-12T19:29:58.330 に答える
0
def fib():
    a,b = 1,1
    num=eval(input("Please input what Fib number you want to be calculated: "))
    num_int=int(num-2)
    for i in range (num_int):
        a,b=b,a+b
    print(b)
于 2011-06-27T20:42:31.413 に答える
0

古典的なフィボナッチ数列に基づいており、ワンライナーのために

インデックスの数だけが必要な場合は、reduce を使用できます ( reduceがこれに最適でなくても、良い練習になる可能性があります)。

def fibonacci(index):
    return reduce(lambda r,v: r.append(r[-1]+r[-2]) or (r.pop(0) and 0) or r , xrange(index), [0, 1])[1]

完全な配列を取得するには、or (r.pop(0) and 0) を削除するだけです

reduce(lambda r,v: r.append(r[-1]+r[-2]) or r , xrange(last_index), [0, 1])
于 2015-02-11T18:01:18.047 に答える
0

http://projecteuler.net/problem=2を通過するだけで、これが私の見解でした

# Even Fibonacci numbers
# Problem 2

def get_fibonacci(size):
    numbers = [1,2]
    while size > len(numbers):
        next_fibonacci = numbers[-1]+numbers[-2]
        numbers.append(next_fibonacci)

    print numbers

get_fibonacci(20)
于 2013-09-12T11:53:24.797 に答える
0
def fib(n):
    """
    n >= 1, the number of elements in the Fibonacci sequence
    """
    x, y = 0, 1
    for i in range(n):
        yield x
        x, y = y, x + y
于 2020-08-16T13:43:14.173 に答える
0

私が Python を学ぶときに使用したチュートリアルの 15 分後、3 つの入力数値 (最初のフィボナッチ数、2 番目の数値、数列を停止する数値) からフィボナッチ数列を計算するプログラムを作成するよう読者に求めました。チュートリアルでは、変数、if/then、およびその時点までのループのみを取り上げました。関数はまだありません。次のコードを思いつきました:

sum = 0
endingnumber = 1                

print "\n.:Fibonacci sequence:.\n"

firstnumber = input("Enter the first number: ")
secondnumber = input("Enter the second number: ")
endingnumber = input("Enter the number to stop at: ")

if secondnumber < firstnumber:

    print "\nSecond number must be bigger than the first number!!!\n"

else:

while sum <= endingnumber:

    print firstnumber

    if secondnumber > endingnumber:

        break

    else:

        print secondnumber
        sum = firstnumber + secondnumber
        firstnumber = sum
        secondnumber = secondnumber + sum

ご覧のとおり、これは非常に非効率的ですが、機能します。

于 2011-10-24T07:53:33.303 に答える
0

基本的にRubyから翻訳:

def fib(n):
    a = 0
    b = 1
    for i in range(1,n+1):
            c = a + b
            print c
            a = b
            b = c

...

于 2015-10-22T23:09:13.970 に答える
0

この問題を解決するために再帰関数を回避しようとしていたため、反復的なアプローチを採用しました。私はもともとメモ化された再帰関数を実行していましたが、最大の再帰深度に達し続けました。また、厳密なメモリ目標を設定していたので、ループ プロセス中は常に配列内に 2 ~ 3 個の値を保持するだけで、配列をできるだけ小さく保っていることがわかります。

def fib(n):
    fibs = [1, 1] # my starting array
    for f in range(2, n):
        fibs.append(fibs[-1] + fibs[-2]) # appending the new fib number
        del fibs[0] # removing the oldest number
    return fibs[-1] # returning the newest fib

print(fib(6000000))

私のマシンでは、600 万番目のフィボナッチ数を取得するのに約 282 秒かかりますが、600k のフィボナッチ数はわずか 2.8 秒しかかかりません。メモ化されたものであっても、再帰関数でそのような大きなフィボナッチ数を取得できませんでした。

于 2015-12-31T05:51:31.470 に答える
0

シンプルなフィボナッチ数列:

def fib(x):
    b = 1
    c = 0
    print(0)
    for i in range(x - 1):
        a = b
        b = c
        c = a + b
        print(c)
于 2021-08-02T18:24:12.450 に答える