くーぱぱのエンジニア作業ログ

一児の父で、エンジニアの、日々の作業記録です

STEP1-4 演習7 解説 part1

初心者が躓きそうなところ

下記記事で紹介した演習サイトは非常に良いです。

STEP1-2 pythonの構文を調べる - くーぱぱのエンジニア作業ログ

ただし学生さん以外は答えを知りません。

あってるか確認する方法も、解決するためのサンプルコードもないため、挫折したときに手の打ちようがないですね。

ということで、躓きそうなこの章は、解説しながら解いていきたいと思います。

演習7-1

問:

解1:

def power(x, n):
    return x ** n

x = float(input('please input x = '))
n = int(input('please input real num n = '))

print(power(x, n))

解説①

こちらは、非常に簡単ですね。

Pythonでは、標準で冪乗の演算が可能です。

なので、以下の手順で計算しているだけになります。

1.入力を受付け、xとnを取得する

x = float(input('please input x = '))
n = int(input('please input real num n = '))

2.関数に受け取ったパラメータを渡す

print(power(x, n)) 

3.関数では、冪乗演算の結果を返却する

def power(x, n):
    return x ** n

ただしこれは、問題の解答ではありますが、出題者の意図に沿った解ではないですね。

この程度であれば、関数化させる必要性がないので。

次は、この演習問題に到達するまでに得た知識をもとに、関数化に取り組んでみます。

解2:

def power(x, n):
    sum = 1
    for i in range(0, n):
        sum *= x
    return sum

x = float(input('please input x = '))
n = int(input('please input real num n = '))

print(power(x, n))

解説②

for文を使った解法ですね。

問題をプログラム的に読み替えると、

n回xを掛け算しろ

と、読み替えられます。

なので、n回のループ処理を行い、xを掛け合わせる処理を実現しました。

似たような処理は、while文でも実現できますね。

解3:

おそらく次の問題も加味すると、この解法が出題者の意図と思われます。

def power(x, n):
    if n == 0:
        return 1
    else:
        return power(x, n - 1) * x

x = float(input('please input x = '))
n = int(input('please input real num n = '))

print(power(x, n))

解説③

ポイントは問題を以下のように読み替えることです。

xのn乗は、xのn - 1乗にxを掛け算した答えだ!

数学的には当たり前の話ですね。

先程読み替えた文章を、よりプログラムチックに書くとこうなります。

power(x, n) = power(x, n - 1) * x

お気づきかと思いますが、power関数内で、再度power関数を呼び出していますね。

このように、自分自身の関数を、関数の処理内で呼び出す関数を、再帰関数と言います。

こうすることで、ややこしい(?)ループ処理などを実装することなく、解を得ることができます。

参考:再帰関数を学ぶと、どんな世界が広がるか - Qiita

再帰関数を理解するための最もシンプルな例 - Qiita

https://wa3.i-3-i.info/word14899.html

慣れるとどーってことはないんですが、慣れるまでは理解に苦しみます。

要点としては、

  1. 終了条件を定義する

  2. 終了条件に収束するように自分自身を呼び出す

というイメージです。

自分自身を呼び出すので、何度も何度も呼び出されますよね?

終わりに向かわなければ、無限に処理し続けてしまいます。(いわゆる無限ループ)

なので、自分自身を呼び出さない条件(=終了条件)を定義し、そこに向かって収束するように自分自身を呼び出すように作ります。

実際の実装にコメントを入れて補足します。

def power(x, n):
    if n == 0: #ここが終了条件
        return 1
    else:
        # nが0(終了条件)に収束する様に、
        # 自分自身を再度呼び出す
        return power(x, n - 1) * x

再帰関数自体は、慣れないうちは処理も追いづらいしメリットも少ないと感じるかもしれません。

実際にシステム開発のなかで、多用する機会はあまりない気がします。

ですが、このあとのフィボナッチ数列の問題や、よくあるのはハノイの塔なども再帰関数で、非常にシンプルなコードで処理できます。

シンプルなコードは不具合が少なくなり、また、メンテナンス性や可読性を引き上げます。

こんな使い方もできるんだな、この方が他の人が読んだときにもわかりやすいな、などと考えられるようになるためにも、マスターしておくと良いかなと思います。

以上、くーぱぱでした。