Python 3 で数学を。

Python 3 とライブラリで数学の問題を解いていきます。統計学や機械学習はときどき。

Python (Python 3) で数学をやるにはどうしたらいいか。その16. 方程式。"バスケットケースのなかに何がいるってそりゃ精神分析医さ!"

このシリーズの過去記事は以下にまとめてある

py3math.hatenablog.com

当記事について

当ブログ筆者も、Python で数学をやるにはどうしたらいいか悩んでいた時期があるから、昔の自分に向けて書いたような記事。

対象とする読者

Python の入門書を一冊か二冊、一通りやった人で、Python の基本的な構文や基本的な用語がだいたいわかっている人。

そして、公式サイトを読む努力をちゃんとする人。

方程式を解いてみよう

SymPy で 2 次方程式 (二次方程式) を解いてみよう。

早速、対話モードから SymPy をインポートしよう (当記事では、Python コードはすべて対話モードで書き、プログラムは 1 例)。

>>> import sympy as sym

数式: x^2 = 49 をまずは解いてみよう。

x を記号として用意しよう。

>>> x = sym.Symbol('x')
>>> x
x

次は、数式を SymPy で扱えるように作成する。SymPy の Eq() を使用する。

>>> expr1 = sym.Eq(x**2, 49)
>>> expr1
Eq(x**2, 49)
>>> sym.pprint(expr1)
 2
x  = 49

これは例えば、日本語で表現すれば、Eq(左辺, 右辺) だ。

以下のようにしないようにちょっと注意してほしい。

>>> x**2 == 49
False

では、方程式を解いてみよう。SymPy の solve() を使用する。

>>> sym.solve(expr1)
[-7, 7]

答えは合っている。

solve() の第 2 引数に、dict=True を書いて、辞書 (dict) として出力してみよう。

>>> sym.solve(expr1, dict=True)
[{x: -7}, {x: 7}]

自分の好きなほうで出力すればいよい (以下では、dict=True を使用する)。

では、練習のため、どんどん式を作成し、解いていこう。

数式: 4x^2 = 64

>>> expr2 = sym.Eq(4*x**2, 64)
>>> sym.solve(expr2, dict=True)
[{x: -4}, {x: 4}]

数式: 5x^2 - 7 = 0

>>> expr3 = sym.Eq(5*x**2 - 7, 0)
>>> sym.solve(expr3, dict=True)
[{x: -sqrt(35)/5}, {x: sqrt(35)/5}]
>>> s1 = sym.solve(expr3, dict=True)
>>> sym.pprint(s1)
⎡⎧   -√35 ⎫  ⎧   √35⎫⎤
⎢⎨x: ─────⎬, ⎨x: ───⎬⎥
⎣⎩     5  ⎭  ⎩    5 ⎭⎦

数式: (x + 3)^2 = 25

>>> expr4 = sym.Eq((x + 3)**2, 25)
>>> sym.solve(expr4, dict=True)
[{x: -8}, {x: 2}]

数式: x^2 + 7x + 3 = 0

>>> expr5 = sym.Eq(x**2 + 7*x + 3, 0)
>>> sym.solve(expr5, dict=True)
[{x: -7/2 - sqrt(37)/2}, {x: -7/2 + sqrt(37)/2}]
>>> s2 = sym.solve(expr5, dict=True)
>>> sym.pprint(s2)
⎡⎧     7   √37⎫  ⎧     7   √37⎫⎤
⎢⎨x: - ─ - ───⎬, ⎨x: - ─ + ───⎬⎥
⎣⎩     2    2 ⎭  ⎩     2    2 ⎭⎦

このようにして簡単に方程式を解くことができる。

では、for 文で一括処理してみよう。

ざっと眺めてみてほしい。

>>> expressions = [[x**2, 49],
...                [4*x**2, 64],
...                [5*x**2 - 7, 0],
...                [(x + 3)**2, 25],
...                [x**2 + 7*x + 3, 0]]
>>>
>>> for idx, expr in enumerate(expressions, 1):
...     print('({})\n'.format(idx))
...     sym.pprint(sym.solve(sym.Eq(*expr), dict=True))
...     print('')
...     print('-'*79)
...
(1)

[{x: -7}, {x: 7}]

-------------------------------------------------------------------------------
(2)

[{x: -4}, {x: 4}]

-------------------------------------------------------------------------------
(3)

⎡⎧   -√35 ⎫  ⎧   √35⎫⎤
⎢⎨x: ─────⎬, ⎨x: ───⎬⎥
⎣⎩     5  ⎭  ⎩    5 ⎭⎦

-------------------------------------------------------------------------------
(4)

[{x: -8}, {x: 2}]

-------------------------------------------------------------------------------
(5)

⎡⎧     7   √37⎫  ⎧     7   √37⎫⎤
⎢⎨x: - ─ - ───⎬, ⎨x: - ─ + ───⎬⎥
⎣⎩     2    2 ⎭  ⎩     2    2 ⎭⎦

-------------------------------------------------------------------------------

出力には問題ないようだ。

だが、for 文内の sym.pprint(sym.solve(sym.Eq(*expr), dict=True)) を見てほしい。

1 行に詰め込み過ぎているような気がしないだろうか。

書いているほうはこれでもよいかもしれない。

だが、読むほうはどうだろうか。読み解くのが大変かもしれない。

ぜひ読みやすく書き換えてみてほしい。

例えば、適切な変数に代入するなどしてみてほしい。

だが、上の for 文のままでよいと思うならそのままでもよい。

(つづく)。

参考文献 (数式を参考)

チャート式体系数学2代数編―中高一貫教育をサポートする

チャート式体系数学2代数編―中高一貫教育をサポートする