引数と戻り値
1.1 を掛けると 1 円ずれる
おこづかい帳では、税抜の値段から税込の値段を出したい場面があります。素直に考えれば price * 1.1 ですが、これはやってはいけません。
Python
print(0.1 + 0.2)
print(290 * 1.1)0.30000000000000004 と 318.99999999999994 が出ます。Python の小数計算には、ごくわずかな誤差があります。切り捨てれば 318 になり、正しい 319 から 1 円ずれます。
避け方は、整数のまま計算し切る ことです。先に整数を掛けてから割れば、途中も答えも整数のままです。
Python
price = 500
print(price * 70 // 100)350 が出ます。3 割引をこの形で書いたわけです。// は切り捨て除算で、必ず小さいほうへ丸めます。円やポイントのように「1 円未満が存在しない」値は、この形で扱うのが定石です。
小数の誤差はバグの温床です。金額の計算を見たら、まず小数が混ざっていないかを確かめます。
材料の入口と、答えの出口
関数は、材料を渡すと答えを返してくれる箱です。材料の入口が 引数、答えの出口が 戻り値 です。かっこの中にカンマ区切りで並べた名前が、そのまま関数の中の変数になります。
Python
def join_words(a, b):
return a + " " + b
print(join_words("今日の", "支出"))a に "今日の"、b に "支出" が入ります。書いた順に前から詰まっていく のが基本の渡し方で、これを位置引数と呼びます。順番を入れ替えれば入る値も入れ替わるので、引数の順を取り違えると、エラーは出ないのに答えだけが狂います。いちばん見つけにくい種類のバグです。
数が合わないときは TypeError になり、missing 1 required positional argument と教えてくれます。
return した値は、その場所にそのまま置き換わります。だから関数の呼び出しは式の中に直接書けますし、別の関数の中から呼ぶこともできます。小さな関数を組み合わせていくと、1 つひとつは短いまま、できることだけが増えていきます。
同じ割り算でも / と // は別の答えを返す
Python
print(300 / 100)
print(300 // 100)3.0 と 3 が出ます。3.0 は小数で、3 とは別の値です。整数が欲しい場面で / を使うと、見た目は合っているのにテストだけが落ちる、という状況になります。
やってみよう
関数 add_tax(price) を実装してください。税抜価格 price を受け取り、消費税 10 パーセントを加えた税込価格を return します。1 円未満は切り捨て、小数を使わず整数のまま計算します。
price が 0 のときは 0 を返します。手元では add_tax(120) が 132 に、add_tax(290) が 319 になることを確かめ、290 * 1.1 を切り捨てた場合との差も見ておいてください。
要件
- 関数名は add_tax で、引数は price の 1 つ
- 戻り値は消費税 10 パーセントを加えた整数の税込価格
- 1 円未満は切り捨てる
- 小数ではなく整数のまま計算する