質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Python 2.7

Python 2.7は2.xシリーズでは最後のメジャーバージョンです。Python3.1にある機能の多くが含まれています。

Q&A

解決済

4回答

2352閲覧

python 漸化式

basketballpyth

総合スコア17

Python 2.7

Python 2.7は2.xシリーズでは最後のメジャーバージョンです。Python3.1にある機能の多くが含まれています。

0グッド

0クリップ

投稿2018/12/02 07:29

漸化式を用いて数字を出力したいのですが自分で考えたコードだといちいち答えを出すのに何回も計算しなければなりません。
(例)get_total_xに5を入れるとしたら1/2.*get_total_x(n-1)+1に代入され
get_total_x(5-1)となりget_total_x(4)も計算しなければなりません。その次は3,2,1と計算されていきます。
その場合計算結果としては合っているのですが計算が遅くなってしまうのでスムーズに
一つ前の計算結果を用いて答えを出力したいのですがどのように変更したらよいのでしょうか。

def get_total_x(n):
if n == 0:
return 0
else:
return 1/2.*get_total_x(n-1)+1

def get_total_y(n):
if n == 0:
return 0
else:
return 1/3.*get_total_y(n-1)+2

def get_total_z(n):
if n == 0:
return 0
else:
return 1/4.*get_total_z(n-1)+3

for i in range(0,50):
print(str(get_total_x(i))+","+str(get_total_y(i))+","+str(get_total_z(i)))

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

まず、提示コードでは計算時間≒get_total_xの呼び出し回数はn+1回で、漸化式を利用している以上、これより減らすことはできません。
しかしたとえばreturn 1/4.*get_total_x(n-1) + 1/4*get_total_x(n-1) + 1と書いた場合は、nが大きくなるにつれ計算時間は急速に増えます。
実際にまずn=20でやってみてください。さらにn=50だと計算終わらないと思います。

計算時間を抑えるには、一般的にはメモ化という手法をとります。
これは、計算済みの結果をどこかにメモしておき、すでに計算済みならメモしたものを返すことにより同じ計算をしないようにする手法です。

今回の例だと以下のようなコードになります。

Python

1 2def get_total_x(n,memo): 3 4 # すでに計算済み 5 if n in memo: 6 return memo[n] 7 8 ret = 0 9 if n == 0: 10 ret = 0 11 else: 12 ret = 1/4.*get_total_x(n-1,memo)+1/4.*get_total_x(n-1,memo)+1 13 14 memo[n] = ret # メモに記録 15 return ret 16 17memo = {} # メモとして辞書を利用 18print(get_total_x(50,memo)) # 1.9999999999999982

ちなみにこのメモ化を自動でやってくれるのがLouiS0616さんの回答にあるfunctools.lru_cacheです。

投稿2018/12/02 09:05

can110

総合スコア38266

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

Python3.2以降であれば、functools.lru_cacheが使えます。
Python2.7のサポートは2020年に終了されますので、乗り換えを強く推奨します。

どうしても古いバージョンを使いたいなら、サードパーティライブラリを利用すると楽です。
StackOverflow - memoization library for python 2.7
GitHub - repoze/repoze.lru

コードの書き方について

teratailには、コードを見やすく表示する機能があります。
質問編集画面を開き、コードを選択した状態で<code>ボタンを押してください。
Python
特にPythonの場合、インデントが崩れるとコードの意味が変わってしまいます。

投稿2018/12/02 07:53

編集2018/12/02 07:56
LouiS0616

総合スコア35660

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

... 一つ前の計算結果を用いて答えを出力したい ...

メソッドに prev として、一つ前の計算結果を指定できるように書き換えてみました。
さらに get_total_x, get_total_y, get_total_z を別関数でなく、
一つの関数 get_total にまとめてみました。

xyz.py

python3

1def get_total(n, k, prev): 2 if n == 0: 3 return 0 4 if prev == None: 5 prev = get_total(n - 1, k, None) 6 return 1.0 / (k + 1) * prev + k 7 8 9p1 = None 10p2 = None 11p3 = None 12for i in range(0, 10): 13 p1 = get_total(i, 1, p1) 14 p2 = get_total(i, 2, p2) 15 p3 = get_total(i, 3, p3) 16 print(str(i), ": ", p1, ",", p2, ",", p3)

実行例
前半は質問文にあるコードを 0..10 までループにして実行してます。
後半は上のコードを実行してます。
出力書式は異なってなすが、数値は同じになっています。
イメージ説明

投稿2018/12/02 11:22

katoy

総合スコア22324

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

basketballpyth

2018/12/08 13:08

どのように実行されていくか前半のコードの詳しい解説お願いしてもよろしいでしょうか?
guest

0

(例)get_total_xに5を入れるとしたら1/2.*get_total_x(n-1)+1に代入され

get_total_x(5-1)となりget_total_x(4)も計算しなければなりません。その次は3,2,1と計算されていきます。

漸化式ってそういうものですよね?

一つ前の計算結果を用いて答えを出力したいのですがどのように変更したらよいのでしょうか。

何番目はこの式で求まるという式を導いて、それに当てはめればよいでしょう。
等差数列とか等比数列とかそんな感じですね。

投稿2018/12/02 07:48

dice142

総合スコア5158

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問