Python

【教科書解説】Pythonプログラミング入門 (CHAPTER 3 変数と関数の基礎) 練習問題

東大/京大のプログラミングの授業でも使われている(無料で読める、東大/京大の「Python教科書」電子書籍)、「Pythonプログラミング入門」の練習問題の解説を連載しています。

この記事では、CHAPTER 3 「変数と関数の基礎」 の問題を紹介します。

この連載シリーズでは、教科書に載っている解答が最適でない場合や、明らかに間違っている場合についても、より良い解法や別解を掲載します。
自分の解法が正解か不安な方も参考になると思います。

教科書のHTML版やPDF版のリンクも掲載していますので、是非ともご活用ください。(この記事ではPDF版の章立てを基準にしています)
教材リンクはこちら↓

3.2.2 練習 ft_to_cm

f フィート i インチをセンチメートルに変換する関数 ft_to_cm(f,i) を定義してください。
ただし、1フィート = 12 インチ = 30.48 cm としてよい。

3.2.2 回答

模範解答は以下の様になっています。
この回答は、単純に「フィートをセンチに変換したもの」と「インチをセンチに変換したもの」を足し合わせたものになっています。

def ft_to_cm(f, i):
    return 30.48 * f + (30.48 / 12) * i

出力結果は、
ft_to_cm(5, 2) = 157.48000000000002
ft_to_cm(6, 5) = 195.57999999999998

別解1

フィートをインチに変換して、単位を揃えてからインチあたりのセンチを掛けたものです。

def ft_to_cm(f, i):
    return (f * 12 + i) * (30.48 / 12)

出力結果は、
ft_to_cm(5, 2) = 157.48
ft_to_cm(6, 5) = 195.58

別解2

インチをフィートに変換して、単位を揃えてからフィートあたりのセンチを掛けたものです。

def ft_to_cm(f, i):
    return (f + i / 12) * 30.48

出力結果は、
ft_to_cm(5, 2) = 157.48000000000002
ft_to_cm(6, 5) = 195.58

3.2.2 解説

なぜ数学的にはどれも正しい式なのに出力結果が異なるのでしょうか?
それは、Pythonや他のプログラミング言語で実数を表すとき、コンピュータの内部では浮動小数点という形式で保持されているからです。
浮動小数点は正確な小数を表しているものではなく、あくまでも近似値に過ぎないということを覚えておくべきです。
プログラムの処理の順番により誤差が大きくなる場合がありますので、誤差が少ない計算方法がよりよい回答ということになります。

整数での計算では誤差は生じませんから、プログラムではなるべく実数による計算を行わないようにすることが重要になります。
上記の回答例の実数による計算回数をカウントしてみると、模範解答と別解2が3回、別解1が2回となっています。
別解1が誤差が最も少なくなる可能性が高いので、より良い回答であると言えそうです。

浮動小数点についてもっと詳しい情報を知りたい方は、15. 浮動小数点演算、その問題と制限 - Python 3.11.2 ドキュメント を参照してください。

また、回答の確認に使われている、

assert round(ft_to_cm(5, 2) - 157.48, 6) == 0
assert round(ft_to_cm(6, 5) - 195.58, 6) == 0

組み込み関数 round()とは、小数の値を丸めるもので、上記の例ではft_to_cmの計算結果の小数部分を6桁に丸めています。

3.2.3 練習 quadratic

二次関数 f(x) = ax^2 + bx + c の値を求める quadratic(a,b,c,x) を定義してください。

3.2.3 回答

模範解答では、a * x * x + b * x + c を計算して値を返しています。

def quadratic(a, b, c, x):
    return a*x*x + b*x + c

別解

xの2乗は、x**2 と表せます。

def quadratic(a, b, c, x):
    return a*x**2 + b*x + c

3.2.3 解説

大きな問題では無いですが、xの2乗を x * x と表すよりも別解のように x**2 と素直に2乗を表現した方が綺麗なように思います。

x**2の方が二次関数の定義を素直に表現出来ているし、2乗を10乗に変えるときのソースコードの変更量が少ない修正ミスが起きにくい等のメリットがあり、模範解答に勝ります。

3.7.1 練習 qe_disc qe_solution1 qe_solution2

二次方程式 ax^2 + bx + c = 0 に関して以下のような関数を定義してください。
 1. 判別式 b^2 − 4ac を求める qe_disc(a,b,c)
 2. 解のうち、大きくない方を求める qe_solution1(a,b,c)
 3. 解のうち、小さくない方を求める qe_solution2(a,b,c)
ただし、qe_solution1 と qe_solution2 は qe_disc を使って定義してください。 
二次方程式が実数解を持つと仮定してよいです。

3.7.1 回答

模範解答は以下になります。

def qe_disc(a, b, c):
    return b*b - 4*a*c

def qe_solution1(a, b, c):
    return (-b - math.sqrt(qe_disc(a, b, c))) / (2*a)

def qe_solution2(a, b, c):
    return (-b + math.sqrt(qe_disc(a, b, c))) / (2*a)

別解

bの2乗は、b**2 と表せます。

def qe_disc(a, b, c):
    return b**2 - 4*a*c

def qe_solution1(a, b, c):
    return (-b - math.sqrt(qe_disc(a, b, c))) / (2*a)

def qe_solution2(a, b, c):
    return (-b + math.sqrt(qe_disc(a, b, c))) / (2*a)

3.7.1 解説

この問題の模範解答も、3.2.3の問題と同様にbの2乗を b * b として表しています。
別解の様に乗数として表すことをオススメします。

参考

前のCHAPTERはこちら

【教科書解説】Pythonプログラミング入門 (CHAPTER 2) 練習問題の回答と解説

東大/京大のプログラミングの授業でも使われている(無料で読める、東大/京大の「Python教科書」電子書籍)、「Pythonプログラミング入門」の練習問題の解説を連載しています。 この記事では、CHA ...

続きを見る

次のCHAPTERはこちら

【教科書解説】Pythonプログラミング入門 (CHAPTER 4 論理・比較演算と条件分岐の基礎) 練習問題

東大/京大のプログラミングの授業でも使われている(無料で読める、東大/京大の「Python教科書」電子書籍)、「Pythonプログラミング入門」の練習問題の解説を連載しています。 この記事では、CHA ...

続きを見る

分かりにくい点や他にも解説して欲しい内容があれば、コメント欄か以下のフィードバックからメッセージをお願いします!

この記事は役に立ちましたか?

  • この記事を書いた人
アバター画像

ゴイチ

ソフトウェアエンジニア歴20年。 C/C++, C#, Java, Kotlinが得意で、組込系・スマホ・大規模なWebサービスなど幅広いプログラミング経験があります。 現在は某SNSの会社でWebエンジニアをしています。

-Python
-, ,