絶対値の演算

絶対値の演算

Pythonで絶対値を計算する

 実数 $x$ の 絶対値 $|x|$ は数直線上の原点からの距離を表します:
 
\[|x|=\begin{cases}x & (x\geq 0)\\[6pt]
-x & (x\lt 0)\end{cases}\]
 すなわち、正数の絶対値はもとの数と同じですが、負数の絶対値はマイナス符号を取り去って正数となります。Python の組み込み関数 abs() を使って、$-10$ の絶対値が $10$ となることを確認してみましょう。

# PYTHON_ABSOLUTE_01

# In[1]

# -10の絶対値を計算
x = abs(-10)

print(x)
10

 複素数 $z=a+bi$ の 絶対値 は複素平面上の原点からの距離として定義されます:
 
\[|z|=\sqrt{a^2+b^2}\]
 たとえば、$2+3i$ の絶対値は $\sqrt{2^2+3^2}=\sqrt{13}=3.60555\,...$ となります。

# In[2]

# 2+3iの絶対値を計算
z = abs(2+3j)

print(z)
3.605551275463989

 複素数の絶対値の定義は、実数の絶対値の定義を包含します。
 たとえば、$10=10+0i$ の絶対値は $\sqrt{10^2+0^2}=10$ となります。

 NumPy パッケージの numpy.absolute() 関数を使うと、配列の各要素の絶対値をまとめて取得できます。

# In[3]

import numpy as np

# 配列を定義
arr = np.array([0, 1, -1])

# 配列の各要素の絶対値を計算
arr_abs = np.abs(arr)

print(arr_abs)
[0 1 1]

 numpy.absolute() と Matplotlib() を使って、$y=|x|$ のグラフを描いてみます。

# In[4]

import matplotlib.pyplot as plt

# データを作成
x = np.linspace(-4, 4, 33)
y = np.abs(x)

# FigureとAxes
fig = plt.figure()
ax = fig.add_subplot(111)
ax.grid()
ax.set_title("y = |x|", fontsize=16, pad=10)
ax.set_xlabel("x", fontsize=16)
ax.set_ylabel("y", fontsize=16)
ax.set_xlim(-4, 4)
ax.set_ylim(-1, 4)

# y=|x|を青色ラインでプロット
ax.plot(x, y, color="blue")

plt.show()

Python 絶対値のグラフ

 同様にして、関数 $y=f(x)$ の絶対値 $y=|f(x)|$ のグラフを描けます。グラフは $f(x)$ で負になる部分を $x$ 軸対称に折り返した形になります。たとえば、次のコードは、$y=\sin x$ と $y=|\sin x|$ のグラフを表示します。

# In[5]

import matplotlib.pyplot as plt

# 円周率の表記を設定
pi = np.pi

# データ(x,y)を設定
x = np.arange(0, 2*pi, 0.1)
y1 = np.sin(x)
y2 = np.abs(np.sin(x))

# FigureとAxesを設定
fig = plt.figure()
ax = fig.add_subplot(111)
ax.grid()
ax.set_title("y = |sinx|", fontsize=16, pad=10)
ax.set_xlabel("x", fontsize=16)
ax.set_ylabel("y", fontsize=16)
ax.set_xlim(0, 2 * pi)
ax.set_ylim(-1.5, 1.5)
ax.set_xticks([0, pi/2, pi, 3*pi/2, 2*pi])
ax.set_xticklabels(["0", "$\pi/2$", "$\pi$", "$3\pi/2$", "$2\pi$"],
                   fontsize = 12)

# データをプロット
ax.plot(x, y1, linestyle="--", color="blue", label="y = sinx")
ax.plot(x, y2, color="red", label="y = |sinx|")
ax.legend()

plt.show()

Python 三角関数の絶対値 |sinx|

 実数 $|x|$ の絶対値は、$x_1$ と $x_2$ の最大値 (小さくないほうの値) をとる関数 $\max()$ を使って、
 
\[|x|=\max(x,-x)\]
と表すこともできます。$x$ と $-x$ のうち、片方は必ず正の値となるからです。たとえば、$-13$ の絶対値は
 
\[\max(-13,13)=13\]
となって、$|-13|$ と同値です。組み込み関数 max() を使って確認してみましょう。

# In[6]

# -13の絶対値
y = max(-13, 13)

print(y)
13

 とはいえ、複素数の大きさは比較できないので、$\max()$ 関数による定義は引数が実数である場合に限定されます。

 実数 $x$ を $|x|$ で割ると、$x$ の符号 ($+1$ または $-1$) が得られます。すなわち、$f(x)=x/|x|$ は符号関数です (ただし、$0$ では除算できないので、$x=0$ のときは $f(0)=0$ とします)。abs() 関数を使って符号関数を定義してみましょう。

# In[7]

# 符号関数を定義
def sign(x):
    if x == 0:
        return 0
    else:
        return x / abs(x)

# -23の符号を得る
val = sign(-23)

print(val)
-1.0

 Python 本体、および各種ライブラリで使用できる絶対値関数を以下にまとめておきます。
 

abs(x)

 Python 本体に組み込まれている abs(x) は引数 x の 絶対値 を返します。x に整数を渡すと整数型を返します。

# PYTHON_ABS

# In[1]

# 整数の絶対値
x = abs(-100)

print(x)
100

 浮動小数点数を渡すと、浮動小数点数型で値を返します。

# In[2]

# 浮動小数点数の絶対値
x = abs(-100.0)

print(x)
100.0

 複素数 a + bj を渡すと、引数の絶対値を浮動小数点数型で返します。

# In[3]

# 複素数の絶対値
x = abs(5 + 7J)

print(x)
8.602325267042627

 

math.fabs(x)

 標準ライブラリの mathモジュールをインポートすると、math.fabs(x) を使えるようになります。 math.fabs(x) は引数 x の絶対値を返します (引数に整数、浮動小数点数のいずれを渡しても、戻り値は浮動小数点数型となります)。

# PYTHON_MATH_FABS

# In[1]

import math

# 整数型の絶対値
x = math.fabs(-100)

print(x)
100.0

 math.fabs() に複素数を渡すと TypeError が返ります。

# In[2]

# math.fabs(complex)
x = math.fabs(1+2j)

print(x)
TypeError: can't convert complex to float

 

numpy.absolute(x)

 numpy.absolute(x) は引数 x の絶対値を返します。この関数は numpy.abs(x) という略記で使用することもできます。引数 x には整数、浮動小数点数、複素数、配列 (ndarray) を指定することができます。

# PYTHON_NUMPY_ABSOLUTE

import numpy as np

# 配列を定義
x = np.array([5, -5, 7 + 9j])

# 配列xの各要素の絶対値を計算
x_abs = np.abs(x)

print("x_abs =", x_abs)
x_abs = [5.+0.j -5.+0.j 7.+9.j]

 引数に渡す配列の個々の要素の型が異なっている場合は、最も広い型をもつ要素と同型に揃えた配列を返します。上のサンプルでは、配列 x のなかに複素数型の要素があるので、この配列の絶対値をとると、要素をすべて複素数型に揃えた配列が返ってきます。
 

numpy.fabs()

 numpy.fabs(x) は引数 x の絶対値を返します。引数 x には整数、浮動小数点数、(整数と浮動小数点数を要素にもつ) 配列を指定することができますが、複素数や複素数を要素にもつ配列を渡すことはできません。

# PYTHON_NUMPY_FABS

import numpy as np

# 配列を定義
x = np.array([5, -5, -10.0])

# 配列xの各要素の絶対値を計算
x_abs = np.fabs(x)

print("x_abs =", x_abs)
x_abs = [5. -5. -10.]
【技術英語の豆知識】absolute value (絶対値)

 「絶対値」は英語で "absolute value" といいます。absolute は「絶対の、不変な、完全な」を意味する形容詞で、科学分野では

 ・absolute temperature 絶対温度
 ・absolute zero (絶対零度:-273.15C)

などの用語で用いられます。Python の組み込み関数 abs() は absolute の頭文字をとったものです。math.fabs() や numpy.fabs() は戻り値が浮動小数点 (float value) に限定されるという意味で、abs の頭に f をつけています。

mpmath.fabs()

 mpmath.fabs(x) は x の絶対値を返します。

# PYTHON_MPMATH_FABS

# In[1]

from mpmath import *
mp.dps = 10
mp.pretty = True

# -10の絶対値
print(fabs(-10))
10

 複素数の絶対値も計算できます。

# In[2]

# 3+5iの絶対値
z = fabs(3 + 5j)

print(z)
5.830951895

 

sympy.Abs()

 SymPy パッケージをインポートすると、sympy.Abs(x) を使って文字式の絶対値を計算できます。x には数値または記号を含む複素数を渡すことができます。

# PYTHON_SYMPY_ABS

# In[1]

from sympy import Abs, I, symbols

# 記号x,yを定義
x, y = symbols('x y')

# f(x,y)=|x+iy|
f = Abs(x + I*y)

# f(1,1)
val = f.subs([(x, 1), (y, 1)])

print(val)
sqrt(2)

 絶対値記号を含む方程式を解くこともできます。たとえば、
 
\[|x+3|=7\]
という方程式を考えてみましょう。手計算で解く場合、絶対値記号の中身の正負によって場合分けします。$x+3 \geq 0$ すなわち $x \geq -3$ のとき、
 
\[x+3=7\]
より $x=4$ が解であり、$x+3 \lt 0$ すなわち $x \lt -3$ のとき、
 
\[-x-3=7\]
より、解は $x=-10$ となります。SymPy に解かせて確認してみましょう。記号 x を定義するとき、x を実数に制限するために、real=True を指定しておきます。

# In[2]

from sympy import solve

# 記号xを定義
x = symbols("x", real=True) 

# 方程式 |x+3|=7 を解く
solutions = solve(Abs(x + 3) - 7, x)

print(solutions)
[-10, 4]

 

絶対値関数の微分

 絶対値関数 $y=|x|$ は $x=0$ で「尖って」いるので、一般的にこの関数は $x=0$ で微分不可能とされます。しかし、
 
\[\lim_{h \to 0}\frac{f(x+h)-f(x-h)}{2h}\]
によって定義される微分を考えるとき、絶対値関数は $x=0$ においても微分可能で、その値は $0$ となります。このような微分を対称微分とよびます。極限をとらない近似式は中心差分公式とよばれ、数値計算で多用されます。たとえば、SymPy で絶対値関数の微分を実行すると、符号関数 $\mathrm{sign}(x)$ を返すようになっています (≫ 符号関数の詳細についてはこちらの記事を参照してください)。

# ABS_FUNCTION

# In[1]

import sympy as sym

# 実行結果をTeXで表示する
sym.init_printing()

# 数式で使用するシンボルを定義
sym.var('x', real=True)

# y=|x|を微分
expr = sym.Abs(x).diff(x)

expr
\[\operatorname{sign}{\left(x \right)}\]

 sympy.plot() で符号関数 ($y=|x|$ の導関数) のグラフを描いてみます。

# In[2]

# sign(x)をプロット
sym.plot(dydx, line_color="navy")

SymPy plot sign(x)

 $\mathrm{sign}(x)$ は $x \gt 0$ で $1$、$x \lt 0$ で $-1$ の値をとります (それぞれの領域における $y=|x|$ の傾きです)。そして、$x=0$ においては $\mathrm{sign}(0)=0$ と定義されています ($y=|x|$ の対称微分が $0$ になるのに対応しています)。

 次はもっと複雑な絶対値関数
 
\[y=|x^2-3x-5|\]
の導関数を調べてみましょう。以下のコードを実行すると、導関数を表示し、もとの関数と導関数を色分けして描画します。

# In[3]

# y=|x**2-3x-5|
y = sym.Abs(x**2 - 3*x - 5)

# yを微分する
dy_dx = y.diff(x)

# 導関数を表示
display(dy_dx)

# 関数と導関数をプロット
ax = sym.plot(y, dy_dx, (x,-5,5), legend=True, show=False)
ax[0].line_color = "blue"
ax[1].line_color = "red"

ax.show()
\[\left(3 - 2 x\right) \operatorname{sign}{\left(- x^{2} + 3 x + 5 \right)}\]

sympy plot Abs(x^2-3x-5)

 実行結果を見ると、やはり導関数は符号関数を含む式となっていて、対称微分が $0$ になる箇所が 2 点あります。