1

以前にも似たような質問をしたことがありますが、これは少し異なります。以下は私のトレーニングです。私が得ている答えは、Pythonの組み込み関数を使用して得た答えと一致しません。私が間違っていることを教えてください。組み込み関数の答えは正しいはずです。

私のワークアウト:

def fact_cum(n):
    f = 1
    for x in range(1, n +1):
        f *= x
    print f

fact_cum(1000) 

Python の組み込み関数:

import math
def cumFact(): 
    x = sum(math.factorial(f) for f in range(1000))
    print x

cumFact()
4

2 に答える 2

4

階乗関数は何も返しません。それを次のように変更しprintますreturn

def fact(n):
    f = 1

    for x in range(1, n +1):
        f *= x

    return f

これで、次のように要約できます。

sum(fact(n) for n in range(1, 1000 + 1))

Python 2 を使用しているため、xrange代わりにrange. イテレータを作成するだけrangeで、メモリ内にリストを作成します。xrange

于 2013-02-07T19:02:07.147 に答える
0

まず、誰もが指摘している大きな問題があります。階乗を実際に合計したり、 に渡すことができる値を返したりするのではなくsum、単に階乗を出力しているだけです。

しかし、それを解いたとしても、実際には を計算することにはなりませんsum(math.factorial(i) for i in range(1000))が、sum(math.factorial(i) for i in range(1, 1001)). 前者が必要な場合は、1! ではなく 0! から始める必要があります。

mgilson が指摘したように、階乗ごとに最初からやり直す必要はありません。累積階乗を実行することの要点は、階乗と合計をロックステップで累積できるため、各階乗を 1 回生成するだけで済みます。

import itertools

def factorials():
    fact = 1
    for i in itertools.count(1):
        yield fact
        fact *= i

def cum_factorials():
    cum = 0
    for fact in factorials():
        cum += fact
        yield cum

def cum_factorial(n):
    cf = cum_factorials()
    consume(cf, 1000)
    return next(cf)

(これには、レシピconsumeの関数、またはインポートされた関数が必要です。または、自分で記述する方法は明らかです。)itertoolsmore-itertools


明らかに、累積階乗の無限リストを生成して n 番目のものを選択する必要はありませんが、Haskell プログラマーが言語の選択を笑うのを防ぐことができます。

もっと真剣に、紙の上でこれを行う方法を想像してみてください。まず、階乗のリストを書き留めます。

1
1 * 1 = 1
1 * 2 = 2
2 * 3 = 6
6 * 4 = 24
...

次に、別の列を横に書き、その時点までの階乗を合計します。

1             1
1 * 1 = 1     1 + 1 = 2
1 * 2 = 2     2 + 2 = 4
2 * 3 = 6     4 + 6 = 10
6 * 4 = 24    10 + 24 = 34
24 * 5 = 120  34 + 120 = 154
...           ...

では、Python で同じことを行うにはどうすればよいでしょうか。

1 つのオプションは、次のように、アルゴリズムを順番に記述できるものに再編成することです。

def cum_fact(n):
    cumulative_sum = 1
    latest_factorial = 1
    for i in range(1, n):
        latest_factorial *= i
        cumulative_sum += latest_factorial
    return cumulative_sum

しかし、それは紙の上でやったよりも実際には理解するのが難しく、間違えやすい.

別の方法は、Python に紙で行ったことを実行させる方法を理解することです: 無限シーケンスを取り、そのシーケンスに(1, 2, 3, 4, …)単純な変換を繰り返し適用して新しいものを取得し、別の単純な変換を繰り返し適用して新しいものを取得します。. そして、そのシーケンスの 1001 番目の値が必要なので、最初の 1000 を破棄して次の値を取得します。*=(1, 1, 2, 6, 24, …)+=(1, 2, 4, 10, 34, …)

itertools.count(1)はその最初のシーケンスを提供します(1, 2, 3, …)。次のように記述できます。

def count(n):
    while True:
        yield n
        n += 1

それがジェネレータ関数です。1 つの段落ですべての概念を説明できるとは思いませんが、基本的な考え方は次のとおりです。値を返す代わりに、値のシーケンスを生成します。にヒットするたびyieldに、呼び出し元は値を取得します。次の値を要求するたびに、残ったところから右に移動し、次の まで進みyieldます。インタラクティブ インタープリターでしばらくアイデアを試してみると、うまくいくかもしれませんが、Google でチュートリアルを探したほうがよいでしょう。

次に、折り畳み関数を使用して各変換を適用することもできますが、この時点で熟考するには少し高度すぎる可能性があるため、さらに 2 つのジェネレーター関数を使用して明示的に記述しました。

最後に、consumeそれ自体が少し異なります。これはジェネレーターではなく、次のようにイテレーターを受け取って変更する関数です。

def consume(iter, n):
    for i in range(n):
        next(iter)

したがって、 があり、最初の 3 つの要素があれば[1, 2, 3, 4, 5, 6, …]consumeが得られ[4, 5, 6, …]ます。

于 2013-02-07T19:24:27.443 に答える