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

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

新規登録して質問してみよう
ただいま回答率
85.35%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

解決済

3回答

2748閲覧

再帰処理 エラーも結果も出ないので原因が分からない

opyon

総合スコア1009

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

1グッド

2クリップ

投稿2018/10/10 05:54

編集2018/10/10 08:59

###まとめ
動くか動かないかの切り分けは完全には出来ていませんが特にPythonのVer差でもOS差でも無いような気がします。

GitHub 修正後のコードまとめ

動かなかった環境は以下のとおりです。
全てNG
・OS:Windows10 Home 64bit
・Python:3.6.6 , 3.7.0
・IDE:Eclipse4.8 , Jupyter Notebook
コマンドライン

その他コメントより
NG
・3.4.3 on Windows8.1/64bit

OK
・3.7.0

@hayataka2049さんの回答より
Python: What is the hard recursion limit for Linux, Mac and Windows? - Stack Overflow
Windows版Pythonの再帰呼び出し制限 - kusano_kの日記

sys.setrecursionlimit(1024*1024)

で再帰呼び出しの深さ制限を変更できるけど、Pythonのスタックサイズが足りないらしく、Pythonが不正終了する。Windowsの場合、新しく作成されるスタックのサイズを
thread.stack_size(12810241024)
で変更できる。

@LouiS0616さん回答より
@functools.lru_cache(maxsize=128, typed=False)

関数をメモ化用の呼び出し可能オブジェクトでラップし、最近の呼び出し最大 maxsize 回まで保存するするデコレータです。高価な関数や I/O に束縛されている関数を定期的に同じ引数で呼び出すときに、時間を節約できます。

 

フィボナッチ数列絡みの問題を再帰で実装する際は、

functools.lru_cache でメモ化するとトラブルが少ないです。

どちらのコードも試してみて動作確認出来ました。
個人的にはimportと@デコレータ追記だけなのでこちらが実用的かとは思います。

追記補足:
但し質問時の元のコードのままで@デコレータ追記だけでは動きませんでした。
@LouiS0616さん回答のように関数を分割すると動きました。
GitHub 修正後のコード qa151136_ok2.py

from functools import lru_cache # @lru_cache(maxsize=None) @lru_cache(maxsize=8) def fibo(n):

Pythonで再帰階層が深くなる場合には気をつけるという教訓にもなりました。
回答やコメントなどでの情報提供ありがとうございました。

###知りたいこと
エラーも結果も出力されない原因が知りたいです。
原因が分かる方いらっしゃればご教示お願いします。

###起きている現象
Problem 25 : 1000-digit Fibonacci number
上記問題を解くのに下記プログラムでN=1000を入力すると正解が出力されるはずなのですが、
関数の再帰処理を使い入力値をN=823以上にすると結果もエラーも表示されずに終了してしまいます。

###実行環境
Windows10
Python3.7.0

Python3

1import sys 2import math 3# 再帰回数の上限 4# sys.setrecursionlimit(2100000000) 5sys.setrecursionlimit(10000) 6 7def fibo2(n_1, n_2, count): 8 n = n_1 + n_2 9 count += 1 10 if n >= target: 11 return count 12 return fibo2(n, n_1, count) 13 14# N = 1000で問題を解きたいのに 15# N = 823以上になると結果が表示されない 16# N = 823 17N = 822 18target = 10 ** (N-1) 19print(fibo2(1, 1, 2)) 20 21# 検算 22# N = 3 23# 12

##試したこと
whileループで書き換えると結果が出るので桁数の問題では無いことは確認済みです。

Python3

1def fibo1(target): 2 a, b = 1, 1 3 cnt = 2 4 target -= 1 5 while b < 10 ** (target): 6 cnt += 1 7 a, b = b, a + b 8 return cnt 9 10target = 1000 11print(fibo1(target)) 12# 出力結果 13# 4782

最初は再帰回数の上限でエラーが出たので調べたら上限設定を変更可能と知ったので変更済みです。

import sys # 再帰回数の上限 # sys.setrecursionlimit(2100000000) sys.setrecursionlimit(10000)
LouiS0616👍を押しています

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

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

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

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

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

LouiS0616

2018/10/10 06:01

実行環境は何ですか?
opyon

2018/10/10 06:06 編集

実行環境とはOSのことでしょうか?OSでしたらWindows10-64bitで、Python3でしたら3.7.0です。 質問内容にも追記編集しました。
opyon

2018/10/10 06:15

Jupyter Notebookでも実行出来ないのとクラシュしたとエラーが出たので再起動しようとしたら、windows更新があるようなので実行して再起動してみます。
guest

回答3

0

ベストアンサー

手元環境のwindowsで、823回では問題ありませんでしたが、850回程度まで増やしてコマンドプロンプトから実行すると強制終了(「python.exeは動作を停止しました」ダイアログが出てそのまま終了)になりました。

あまり詳しくありませんが、この辺の話だと思います。

Python: What is the hard recursion limit for Linux, Mac and Windows? - Stack Overflow

Windows版Pythonの再帰呼び出し制限 - kusano_kの日記

sys.setrecursionlimit()はインタプリタ側の設定を変更するだけで、実際にスタックとして使える領域の容量には別途制限がある・・・ということらしいです。ややこしいですが。

以下のコードに書き換えて実行できることを確認しました。

python

1# coding: UTF-8 2import sys 3import threading 4sys.setrecursionlimit(2100000000) 5threading.stack_size(128*1024*1024) # 追加 6 7def fibo2(n_1, n_2, count): 8 n = n_1 + n_2 9 count += 1 10 if n >= target: 11 return count 12 return fibo2(n, n_1, count) 13 14def f(): 15 global target # 汚いけどとりあえず 16 N = 1000 17 target = 10 ** (N-1) 18 print(fibo2(1, 1, 2)) 19 20threading.Thread(target=f).start()

投稿2018/10/10 06:17

hayataka2049

総合スコア30935

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

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

opyon

2018/10/10 06:21

ありがとうございます。 今コピペして動作確認出来ました。 もう少し調べてみます。
opyon

2018/10/10 06:23

差し支えなければ後学のためにどのような検索などしたのか教えて頂けると助かります。
hayataka2049

2018/10/10 07:09 編集

python recursion windowsとかでググってたら上のリンクのスタックオーバーフローを見つけて、あとはそこからキーワードを拾って芋づる式に
opyon

2018/10/10 06:28

なるほど、ありがとうございます。 日本語で再帰で検索していました。 recursionが再帰という意味も今知りました。 最初から英語で調べることが大事なのですね。
guest

0

フィボナッチ数列絡みの問題を再帰で実装する際は、
functools.lru_cache でメモ化するとトラブルが少ないです。

Python

1from functools import lru_cache 2from itertools import count 3 4 5@lru_cache(max_size=8) 6def fibo(n): 7 if n in (1, 2): 8 return 1 9 10 return fibo(n-1) + fibo(n-2) 11 12 13def fibo2(target): 14 for i in count(start=3): 15 if fibo(i) >= target: 16 return i 17 18 19N = 1000 20target = 10 ** (N-1) 21print(fibo2(target))

今回失敗した原因については、hayataka2049さんのご指摘のとおりかと思います。

投稿2018/10/10 06:30

編集2018/10/10 06:32
LouiS0616

総合スコア35668

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

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

opyon

2018/10/10 06:53

ありがとうございます。 最初にmaxsize=8とするとエラーが出て動かず8,16,32と増やしても動かず、Noneにして動きました。 その後再度8に戻すと動きました。再現性が無いのですが一応報告しておきます^^; # @lru_cache(maxsize=None) @lru_cache(maxsize=8)
opyon

2018/10/10 06:55

コードとしてはこちらの方がアノテーション追加だけでシンプルなので実用的ですが、 情報提供面で@hayataka2049さんにBAを送りたいと思います。ご了承ください。
LouiS0616

2018/10/10 07:24

・BAについて 私もそれが適当かと思います。 私の回答は解決法を示しただけで、原因には言及していませんので。 ・アノテーション アノテーションはJavaの用語ですね。 Pythonではデコレータと呼び、わりあい機能も単純です。というか、ただのシンタックスシュガーです。
opyon

2018/10/10 07:26 編集

失礼しました^^; デコレータに訂正しておきます。
guest

0

WindowsでもLinuxでも問題なくN=1000が実行できます。
特殊な実行環境なのでは?ウェブ上とか?

投稿2018/10/10 06:05

otn

総合スコア85901

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

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

opyon

2018/10/10 06:07

ありがとうございます。 環境を変えて試してみます。
otn

2018/10/10 06:22

Windowsでも環境により違うみたいですね。 Python 3.6.2 on Windows7/64bit です。
opyon

2018/10/10 06:24

3.6.6でも動かず、Jupyter Notebookでも動かず・・・ 後ほど試したことを質問内容に書いておきます。
otn

2018/10/10 06:31

動かない原因としては、スタックの不足でしょうが、エラーが出ないというので、ウェブ上のプログラム実行環境なのかなと思っておりました。 出力無しで正常終了したように見えると言う事ですよね? コマンドプロンプトから直接実行した場合もですか?
hayataka2049

2018/10/10 06:31

@otnさん, opyonさん 私はPython 3.4.3 on Windows8.1/64bitでした。公式配布の.exeのインストーラで入れたはず (3.4.3は笑ってください、数年前インストールして最近は放置している常用していない環境です) ビルドによって違うとかかなぁ・・・
LouiS0616

2018/10/10 06:34

Python 3.6.5 Anaconda Windows10/64bit でも無言でヘタりました。
otn

2018/10/10 06:40

たった今、公式サイトで3.7.0に上げてみましたが、N=1000で4782と出ますね。 何が違うんだろう?
opyon

2018/10/10 07:30

何でしょうね・・・ @otnさんの環境がハイスペックとか?
otn

2018/10/10 07:31

再度聞きますが、 コマンドプロンプトから直接実行した場合もですか?
opyon

2018/10/10 07:34

@otnさんへ すみません、コメント見落としていました。 コマンドプロンプトから直接実行したこと無いのですが・・・ すぐには出来ないので時間掛かると思いますが調べて試してみます。
opyon

2018/10/10 07:51

コマンドプロンプトでも無言終了でした。 質問のまとめに画像リンク貼りました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問