【Python】数値型と四則演算
Python3 の数値型は整数型 (int)、浮動小数点数型 (float)、複素数型 (complex) の 3 種類に分類されます。プログラミング言語の種類によってはデータ型を予め宣言しておくものも多いですが、Python では、その数値をどのように記述するかによって数値の型が決まります。
データ型は type()関数によって調べることができます。
100 と記述された数値の型を調べてみましょう。
# Python numeric data type # In[1] print(type(100)) # <class 'int'>
クラスは int であると表示されました。つまり 100 は整数型です。同じ 100 でも 100.0 と書けば浮動小数点数型 (float) となります:
# In[2] print(type(100.0)) # <class 'float'>
浮動小数点数は次のような書き方をすることもできます。
# In[3] # 1.25×10**3 x = 1.25e3 print(x) # 1250
指数部を負にすることもできます。たとえば、1000 × 10-3 は 1000.0e-3 と記述します。
# In[4] print(1000.0e-3) # 1.0
複素数型(complex)は「実部 + 虚部j」の形式で記述します。
# In[5] print(type(2 + 3j)) # <class 'complex'>
Python2 では、扱う桁の大きさに応じて整数型(int)と長整数型(long)の 2 種類が用意されていましたが、Python3 では、両者は桁に上限のない整数型(int)に統合されました。
算術演算子による四則演算
Python3 における算術演算子の種類を確認しておきましょう。基本的な加減乗除(四則演算)は「+」,「-」,「*」,「/」によって実行できます。
加算演算子は「+」で実行します。
# In[6] # 加算(足し算) print(15 + 10) # 25
減算演算子は「-」で実行します。
# In[7] # 減算(引き算) print(15 - 10) # 25
乗算演算子は「*」です。
# In[8] # 乗算(掛け算) print(15 * 10) # 150
除算は「/」で実行します。
# In[9] # 除算(割り算) print(15 / 10) # 1.5
「**」はべき乗を計算します。
たとえば、「10 の 0.5 乗」は次のように記述します。
# In[10] x = 10 ** 0.5 print(x) # 3.1622776601683795
「/」が除算の結果を小数で返すのに対して、「//」は割り算の商だけを返します(このような除算を切り捨て除算とよびます)。
# In[11] x = 10 // 3 print(x) # 3
「//」を使って負の数を割り算するときは注意が必要です。
たとえば -15 を 6 で切り捨て除算すると、計算結果は -2 とはなりません。
-15/6 を超えない最小整数を計算します:
# In[12] x = -15 // 6 print(x) # -3
「%」は剰余演算を実行します。
つまり、割り算したときの余りを返します。
たとえば、10 を 3 で割ったときの余りを計算させるには以下のように記述します。
# In[13] x = 10 % 3 print(x) # 1
型の異なる数値同士の演算
冒頭で Python3 では整数型(int)、浮動小数点数型(float)、複素数型(complex)という 3 種類の数値型があると説明しましたが、もし異なる型の数値同士で演算を行なったらどうなるのか気になるところです。試しに浮動小数点数型の数値 10.0 と整数型の数値 5 を加えてみましょう。
# In[1] 10.0 + 5 # 15.0
結果は浮動小数点数型となっています。
今度は複素数型の 1 + 2i と整数型の 3 を加えてみます。
# In[2] (1 + 2j) + 3 # (4 + 2j)
複素数型で返ってきました。このように、Python では型の異なる数値同士で演算すると、より広いほうの型に合わせられます。
算術演算子の優先順位
演算子には優先順位(プログラム実行時に処理する順序)が決められています。算術演算子の場合は、皆さんが学校の算数や数学で習った順序とほぼ同じです。つまり優先順位の高い順に「()、べき乗、掛け算、割り算、足し算、引き算」となっています。たとえば次のような数式を記述してみます:
# In[1] x = 20/4 + 7 print(x) # 12.0
まず最初に 20 を 4 で割ってから 7 を加えて 12.0 となっています(除算があるので結果は float が返ります)。20 を 4 と 7 を加えた数字で割りたいときには ( ) を使います。
# In[2] x = 20/(4 + 7) print(x) # 1.818181818181
足し算と引き算に優先順位が決められていることを不思議に思うかもしれません。足し算と引き算は順序を変えても結果は同じはずです。これはあくまで Python がプログラム実行時に処理する順番が決まっているというだけのことなので、あまり気にする必要はありません。
算術演算子に割り当てる特殊メソッド
Python のプログラマーは自作クラスの内部に特殊メソッドを組み込むことで、算術演算子に独自の機能を割り当てることができます。具体例を見てみましょう。最初にオブジェクトを受け取って、属性(インスタンス変数)に組み込む単純なクラスを定義します。
# In[1] class Class_A: def __init__(self, obj): self.val = obj
Class_A には足し算が定義されていないので、このクラスのインスタンス同士で「 + 」演算子を使うとエラーが発生します。
# In[2] # Object_Aのインスタンスを生成 x = Class_A(10) y = Class_A(20) # aとbを加える print(x + y) # TypeError: unsupported operand type(s) for +: 'Class_A' and 'Class_A'
そこで、Class_A を次のように書き換えてみます。
# In[3] class Class_A: def __init__(self, obj): self.val = obj # オブジェクトの加算を定義する def __add__(self, other): return self.val + other.val
特殊メソッド __add__(self, other) は val 属性同士を数値的に加えた値を返すように定義されています。
# In[4] x = Class_A(10) y = Class_A(20) print(x + y) # 30
Class_A は「+」に足し算の機能を与えましたが、割り当てる機能は何でも構いません。極端な話、「+」に掛け算の機能を与えることもできます。
# In[5] class Class_B: def __init__(self, obj): self.val = obj # +に掛け算の機能を割り当てる def __add__(self, other): return self.val * other.val x = Class_B(10) y = Class_B(20) print(x + y) # 200
足し算すると “Hello!” と返すようなクラスを作ることもできます。
# In[6] class Class_C: def __init__(self, obj): self.val = obj # オブジェクトの加算を定義する def __add__(self, other): return "Hello!" x = Class_C(10) y = Class_C(20) print(x + y) # Hello!
遊びはこのぐらいにして、もう少し実用的なクラスを設計してみましょう。よく知られているように、文字列同士に「+」を使うと文字列が連結されます。
# In[7] print("りんご" + "みかん") # りんごみかん
これは str クラス内部で __add__() メソッドが文字列を連結するように定義されているからです。文字列と文字列の間に “と” を入れて連結するような新しいクラスを設計してみましょう。
# In[8] class Class_D: def __init__(self, obj): self.val = obj # オブジェクトの加算を定義する def __add__(self, other): return self.val + "と" + other.val x = Class_D("りんご") y = Class_D("みかん") print(x + y) # りんごとみかん
加算以外にも減算や乗算、べき乗などを定義できます。
特殊メソッドと対応する算術演算子を表にまとめておきます。
特殊メソッド | 演算子 |
---|---|
__add__(self, other) | + |
__sub__(self, other) | – |
__mul__(self, other) | * |
__matmul__(self, other) | @ |
__truediv__(self, other) | / |
__floordiv__(self, other) | // |
__mod__(self, other) | % |
__pow__(self, other[, modulo]) | ** |
コメント
【AI連載小説】陽子のプログラミング日記(3)
Anacondaのインストールが完了し、陽子は奏と共にPythonの学習に新たな一歩を踏み出していた。カフェのテーブルには、陽子のラップトップが開かれ、奏が算術演算子について教えていた。
「算術演算子は、数学の四則演算と同じようなものだよ。例えば、足し算は+、引き算は-、掛け算は*、割り算は/だ」
奏(かなで)が言うと、陽子はキーボードを叩きながら、Pythonのコードを書き始めた。
陽子は奏の説明を聞きながら、各演算子の使い方を覚えていった。
「なるほど、これで変数同士の計算ができるんだね」
奏は微笑みながら続けた。
「そうだ。これを使って、プログラムで様々な計算ができるんだ。他にもいろんな演算子があるから、覚えておくと便利だよ」
陽子は興味津々の表情で奏の説明を聞き入れ、Pythonの世界に更なる理解を深めていくのであった。