1-1. 数値演算

数値演算について説明します。

参考

簡単な算術計算

CodeセルにPythonの式を入力して、プレイボタンを押すか、 Shiftを押しながらEnterを押すと、式が評価され、その結果の値がセルの下に挿入されます。

1+1 の計算をしてみましょう。次のセルに 1+1 と入力して、 Shiftを押しながらEnterを押してください。

[ ]:

このようにして、電卓の代わりにPythonを使うことができます。+ は言うまでもなく足し算を表しています。

[1]:
7-2
[1]:
5
[2]:
7*2
[2]:
14
[3]:
7**2
[3]:
49

-引き算*掛け算**べき乗を表しています。

式を適当に書き換えてから、Shiftを押しながらEnterを押すと、 書き換えた後の式が評価されて、セルの下の値はその結果で置き換わります。 たとえば、上の 2100 に書き換えて、7の100乗を求めてみてください。

割り算はどうなるでしょうか。

[4]:
7/2
[4]:
3.5
[5]:
7//2
[5]:
3

Pythonでは、割り算除算)は / で表され、整数除算// で表されます。 // は小数部を切り捨てた整数値()を返します。

整数同士の // の結果は整数になります。

[6]:
7/1
[6]:
7.0
[7]:
7//1
[7]:
7

整数除算の余り剰余)を求めたいときは、別の演算子 % を用います。

整数同士の % の結果は整数になります。

[8]:
7%2
[8]:
1

コメント

Pythonでは一般に、コードの中に # が出現すると、それ以降、その行の終わりまでがコメントになります。 コメントは行頭からも、行の途中からでも始めることができます。

プログラムの実行時には、コメントは無視されます。

[9]:
# このように行頭に '#' をおけば、行全体をコメントとすることができます。

# 次のようにコード行に続けて直前のコードについての説明をコメントとして書くこともできます。
2**10  # 2の10乗を計算します
[9]:
1024
[10]:
# 次のようにコード行自体をコメントとすることで、その行を無視させる(コメントアウトする)こともよく行われます。
# 2**10  # 2の10乗を計算します この行が「コメントアウト」された
2**12  # 実は計算したいのは2の12乗でした
[10]:
4096

整数と実数

Pythonでは、整数と小数点のある数(実数)は、数学的に同じ数を表す場合でも、 コンピュータの中で異なる形式で記憶されますので、表示は異なります。 (実数は浮動小数点数ともいいます。)

[11]:
7/1
[11]:
7.0
[12]:
7//1
[12]:
7

しかし、以下のように、比較を行うと両者は等しいものとして扱われます。 値同士が等しいかどうかを調べる == という演算子については、後で紹介します。

[13]:
7/1 == 7//1
[13]:
True

+-*//%** では、2つの数が整数ならば結果も整数になります。 2つの数が実数であったり、整数と実数が混ざっていたら、結果は実数になります。

[14]:
2+5
[14]:
7
[15]:
2+5.0
[15]:
7.0

/ の結果は必ず実数となります。

[16]:
7/1
[16]:
7.0

ここで、自分で色々と式を入力してみてください。 以下に、いくつかセルを用意しておきます。 足りなければ、Insertメニューを使ってセルを追加することができます。

[ ]:

[ ]:

[ ]:

実数のべき表示

[17]:
2.0**1000
[17]:
1.0715086071862673e+301

非常に大きな実数は、10のべきとともに表示(べき表示)されます。 e+301 は10の301乗を意味します。

[18]:
2.0**-1000
[18]:
9.332636185032189e-302

非常に小さな実数も、10のべきとともに表示されます。 e-302 は10の-302乗を意味します。

いくらでも大きくなる整数

[19]:
2**1000
[19]:
10715086071862673209484250490600018105614048117055336074437503883703510511249361224931983788156958581275946729175531468251871452856923140435984577574698574803934567774824230985421074605062371141877954182153046474983581941267398767559165543946077062914571196477686542167660429831652624386837205668069376

このように、Pythonでは整数はいくらでも大きくなります。 もちろん、コンピュータのメモリに納まる限りにおいてですが。

[20]:
2**2**2**2**2
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
File ~/Projects/utpython/lib/python3.12/site-packages/IPython/core/formatters.py:711, in PlainTextFormatter.__call__(self, obj)
    704 stream = StringIO()
    705 printer = pretty.RepresentationPrinter(stream, self.verbose,
    706     self.max_width, self.newline,
    707     max_seq_length=self.max_seq_length,
    708     singleton_pprinters=self.singleton_printers,
    709     type_pprinters=self.type_printers,
    710     deferred_pprinters=self.deferred_printers)
--> 711 printer.pretty(obj)
    712 printer.flush()
    713 return stream.getvalue()

File ~/Projects/utpython/lib/python3.12/site-packages/IPython/lib/pretty.py:394, in RepresentationPrinter.pretty(self, obj)
    391 for cls in _get_mro(obj_class):
    392     if cls in self.type_pprinters:
    393         # printer registered in self.type_pprinters
--> 394         return self.type_pprinters[cls](obj, self, cycle)
    395     else:
    396         # deferred printer
    397         printer = self._in_deferred_types(cls)

File ~/Projects/utpython/lib/python3.12/site-packages/IPython/lib/pretty.py:787, in _repr_pprint(obj, p, cycle)
    785 """A pprint that just redirects to the normal repr function."""
    786 # Find newlines and replace them with p.break_()
--> 787 output = repr(obj)
    788 lines = output.splitlines()
    789 with p.group():

ValueError: Exceeds the limit (4300 digits) for integer string conversion; use sys.set_int_max_str_digits() to increase the limit

整数と実数の間の変換

実数を整数に変換するには、int という関数を用います。 (関数に関する一般的な説明は1-2を参照してください。) int(x) は、実数 x を(0 の方向に)切り下げた結果を返します。

[21]:
int(2.9)
[21]:
2
[22]:
int(-2.9)
[22]:
-2

逆に、整数を実数に変換するには、float という関数を用います。 float(i) は、整数 i を実数に変換した結果を返します。 たとえば i+0.0 としても、i を実数に変換できます。

[23]:
float(2)
[23]:
2.0
[24]:
2+0.0
[24]:
2.0

数値誤差

浮動小数点数には、数値誤差が不可避です。 これは、有限のビット数で、無限に小さくなり得る小数刻みを表現しようとするためです。 (参照:Wikipedia - 浮動小数点数

Pythonでは、整数は無限桁で表現されるため、整数演算には誤差が生じません。 しかし、整数を実数に変換したときには、一般に誤差が生じます。

[25]:
10**60
[25]:
1000000000000000000000000000000000000000000000000000000000000
[26]:
float(10**60)
[26]:
1e+60
[27]:
int(float(10**60))
[27]:
999999999999999949387135297074018866963645011013410073083904

数え上げのような離散的な値を扱う時には、実数を経由せずに、整数のみで演算するようにしましょう。

演算子の優先順位と括弧

掛け算や割り算は足し算や引き算よりも先に評価されます。 すなわち、掛け算や割り算の方が足し算や引き算よりも優先順位が高いと定義されています。

括弧を使って式の評価順序を指定することができます。

なお、数式 \(a(b-c)\)\((a-b)(c-d)\) は、それぞれ \(a\)\(b-c\)\(a-b\)\(c-d\) の積を意味しますが、 コードでは、a*(b-c)(a-b)*(c-d) のように積の演算子である * を明記する必要があることに注意してください。

また、数や演算子の間には、自由に空白を入れることができます。(後でもう一度説明します。)

[28]:
7 - 2 * 3
[28]:
1
[29]:
(7 - 2) * 3
[29]:
15
[30]:
17 - 17//3*3
[30]:
2
[31]:
56 ** 4 ** 2
[31]:
9354238358105289311446368256
[32]:
56 ** 16
[32]:
9354238358105289311446368256

上の例では、4**2 が先に評価されて、56**16 が計算されます。 つまり、x**y**z = x**(y**z) が成り立ちます。 このことをもって、** は右に結合するといいます。

[33]:
16/8/2
[33]:
1.0
[34]:
(16/8)/2
[34]:
1.0

上の例では、16/8 が先に評価されて、2/2 が計算されます。 つまり、x/y/z = (x/y)/z が成り立ちます。 このことをもって、/ は左に結合するといいます。

*/ をまぜても左に結合します。

[35]:
10/2*3
[35]:
15.0

以上のように、演算子によって式の評価の順番がかわりますので注意してください。

ではまた、自分で色々と式を入力してみてください。 以下に、いくつかセルを用意しておきます。

[ ]:

[ ]:

[ ]:

単項の +-

+- は、単項の演算子(単項演算子)としても使えます。 (これらの演算子の後に1つだけ数が書かれます。 前と後の両方に数が書かれる演算子は2項演算子と言います。)

[36]:
-3
[36]:
-3
[37]:
+3
[37]:
3

算術演算子のまとめ

算術演算子を、評価の優先順位にしたがって、すなわち結合力の強い順にまとめておきましょう。

まず、2項のべき演算子 ** が最も強く結合します。 ** は右の方から計算され、このことを「右に結合する」と表します。

次に、単項の +- が強く結合します。 なお、 ** の右側に単項の +- がある場合は、+- がより強く結合します。 例えば、 -10 ** 2 では ** がより強く結合し -100 となり、 10 ** -2 では - がより強く結合し 0.01 となります。

その次に、2項の *///% が強く結合します。これらは左に結合します。

最後に、2項の +- は最も弱く結合します。これらも左に結合します。

空白

既に 7 - 2 * 3 のような例が出てきましたが、 演算子と数の間や、演算子と変数(後述)の間には、空白を入れることができます。 ここで空白とは、半角の空白のことで、英数字と同様に1バイトの文字コードに含まれているものです。

複数の文字から成る演算子、たとえば **// の間に空白を入れることはできません。 エラーになることでしょう。

[38]:
7 **2
[38]:
49
[39]:
7* *2
  Cell In[39], line 1
    7* *2
       ^
SyntaxError: invalid syntax

全角の空白

日本語文字コードである全角の空白は、空白とはみなされませんので注意してください。

[40]:
7 **2
  Cell In[40], line 1
    7 **2
     ^
SyntaxError: invalid non-printable character U+3000

エラー

色々と試していると、エラーが起こることもあったでしょう。 以下は典型的なエラーです。

[41]:
10/0
---------------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)
Cell In[41], line 1
----> 1 10/0

ZeroDivisionError: division by zero

このエラーは、ゼロによる割り算を行ったためです。 実行時エラーの典型的なものです。

エラーが起こった場合は、修正して評価し直すことができます。 上の例で、0 をたとえば 3 に書き換えて評価し直してみてください。

[42]:
10/
  Cell In[42], line 1
    10/
       ^
SyntaxError: invalid syntax

こちらのエラーは構文エラーです。 つまり、入力がPythonの構文に違反しているため実行できなかったのです。

数学関数(モジュールのインポート)

[43]:
import math
[44]:
math.sqrt(2)
[44]:
1.4142135623730951

数学関係の各種の関数は、モジュールライブラリ)として提供されています。 これらの関数を使いたいときは、上のように、import で始まる import math というおまじないを一度唱えます。 そうしますと、math というライブラリが読み込まれて(インポートされて)、 math.関数名 という形で関数を用いることができます。 上の例では、平方根を計算する math.sqrt という関数が用いられています。

もう少し例をあげておきましょう。sinとcosは math.sinmath.cos で求まります。

[45]:
math.sin(0)
[45]:
0.0
[46]:
math.pi
[46]:
3.141592653589793

math.pi は、円周率を値とする変数です。

変数については後に説明されます。

[47]:
math.sin(math.pi)
[47]:
1.2246467991473532e-16

この結果は本当は 0 にならなければならないのですが、 数値誤差のためにこのようになっています。

[48]:
math.sin(math.pi/2)
[48]:
1.0
[49]:
math.sin(math.pi/4) * 2
[49]:
1.414213562373095

練習

黄金比を求めてください。黄金比とは、5 の平方根に 1 を加えて 2 で割ったものです。約 1.618 になるはずです。

[ ]: