初心者入門

フィボナッチ数列は再帰関数の題材として適切なのか

フィボナッチ数列は再帰関数の題材として適切なのか
『教養としてのコンピュータ・ サイエンス』 ( ⁠渡辺治 著) に 「再帰の極意」 として紹介されていること (P. 59) が, この数学的帰納法についても同様に言えます。つまり, ひとつ後の式 f(k+1) が正しく実行されるために, 今の式 f(k) は正しく実行されると信じ込む, 疑わないことが大切です。こう言及すると, 何か詐欺でも働いているようですが, 再帰ならば最終的な条件, 数学的帰納法ならば初期条件をしっかり定義したのだから大丈夫なのです。どんどん進んで条件に打ち当たれば, その条件に定めた処理を実行するだけです。

フィボナッチ数列は再帰関数の題材として適切なのか

2021/09/19 23:58 編集

日本人が英会話を勉強するときに、二つの考え方があります。 (1) 日本語での会話を瞬時に英語に翻訳して話そうとする。 (2) 英語で考えて英語で話そうとする。 (1)でまともに英会話するのは現実問題として無理です。 おはようございます = Good morning こんにちは = Good afternoon こんばんは = Good evening では、11時にあいさつするときは? とか考えていては会話になりませんね。 Good morning : May you have a good morning と理解していれば、そしてmorningはsunriseからnoonまでだと理解していれば、瞬時に反応できますし応用も利きます。 これと同じように、CでプログラミングするときはCで考え、PythonでプログラミングするときはPythonで考え、再帰でプログラミングするときは再帰で考えるのが楽ですし実用的です。 私は良く再帰のコードを書きますが、その理由は再帰で考える方が楽で、短い時間でコードが書けるからです。しかし、再帰コードは実行性能が悪い(遅い)ことが多いので、性能を気にするときは、最初からループで書きます。 ループで書いたコードを元に再帰コードを作るというのは意味がありませんし効率が悪いと思います。

> maisumakun 確認ありがとうございます。他の方も同じような疑問が浮かぶかと思いましたので、質問の背景を詳細に下記に記載しておきます。 上記のようなコードを再帰実装する上での処理ステップを言語化して人にわかりやすく説明できるようになるため、もしくはより汎用的な説明を見つけるために、わざわざfor-loopから再帰で書こうとしています。 まずは、for-loopを実装して、それから再帰に書き換えてみましょう、という説明の仕方が一番クリアで実装前の実装後を比較しながら対応付けをしつつ理解しやすいと思ったからです。 最初から再帰を実装しろ、という教え方は、誰にでも通じる説明の仕方ではない一方で、for-loopはわりと手続的に理解ができ、処理ステップが理解しやすので、手続的に理解してから命題的に課題を解く、っていう考え方のほうがいいかなと思っています。 仮に最初から再帰的に解けと言われた瞬間に手続的に踏む処理ステップがblack boxになり、ある数式を途中式をかかず説明せずにこれで動くんです、自明である、的な説明で終始しがちになります。その思考癖だとデバックはもとい、これはこうだから動く、なんとく私のローカル環境では動くから正しい、のような思考癖になります。 で、その説明をする上で、上記のようなループがいれくんだ複雑なコードになった瞬間、手続的→命題的に、for-loop→recursionのステップでの理解がしづらくなってきた気がしましたので、どう説明及び言語化したらいいだろうか、というのが質問の背景になります。

IT・技術研修ならCTC教育サービス

教育サービス

Java 5で追加された並行処理のためのjava.util.concurrentパッケージに細かい粒度で並列性を増したFork/Joinフレームワークが Java 7から登場しました。大量の計算を小さく分けてマルチスレッド処理をしようという戦略で、これを分割統治法(Divide and Conquer Algorithm)と呼びます。
いかつい名前ですが、問題を小さく分割して最終的に解決しようとする方法はとても自然です。 フィボナッチ数列は再帰関数の題材として適切なのか フィボナッチ数列は再帰関数の題材として適切なのか
加えてフレームワーク内部ではWork Stealingという方策で最小限のコストで適切にタスクを分配できる実装が為されています。これによりマルチコアCPUを効率的に稼動させる事が出来るのです。

フィボナッチ数列は単に再帰的に足し算するだけの単純な計算のため今回は恩恵を享受できない上にオーバーヘッドのコストが上回ります。
筆者の非力なマシンでは、数値を増やすと目に見えて遅くなりました。
むしろシンプルな線形アルゴリズムを使えば高速に実行できるでしょう。
しかしながら、再帰すべき計算処理が複雑で且つ、多数のコアを有する場合に「コア数を意識することなく記述が可能」で、しかもコア数が増える程に飛躍的に処理速度が向上することでしょう(並列度は指定可能)。つまりメニーコア時代の潤沢な計算資源を有効活用する光明かもしれません。

現在から少しだけ未来の話になりますが、Java 8リリースではFork/JoinフレームワークにParallelArray(並列処理のためのコレクション)が登場して内部イテレータで容易に並列化できる記述が検討されています。
同じくJava 8に持ち越しされたProject Lambdaでラムダ式(クロージャー)が登場し、並列化での冗長な記述を排除し簡潔に表現出来ると期待されます。

アルゴリズムの題材として初等数学のフィボナッチ数を取りあげました。
フィボナッチは神秘的な数列で植物の花弁や葉の数、または巻き貝と一致するのが散見されます。フィボナッチは自然界とリンクしています。
また幾何学的にもフィボナッチ数列の各項を一辺とする正方形を描き、その一辺の中点から対面する角への斜線を半径とした円弧を辺の延長線上まで描き、それを繰り返していくと黄金螺旋(フィボナッチ・スパイラル)なる綺麗な図形が紡ぎ出されます(Sybase社のロゴに使われていました)。
隣り合う正方形一辺の比率は1:1.618(近似値)で黄金比率に収束します。
最も美しいとされる比率です。やはり花弁と同じ比率を美しいと感じ取る人間こそがまさに自然の一部なのだと強く感じます。

CTC教育サービス 関連コース

[IT研修]注目キーワード フィボナッチ数列は再帰関数の題材として適切なのか Python UiPath(RPA) 最新技術動向 Microsoft Azure Docker Kubernetes

関連記事

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする

目次
閉じる