複素数を引数にとる指数関数はオイラー (Euler) の公式から導くことができます。
複素数の対数関数は複素数 z を絶対値 \(|z|\) と偏角 \(\theta\) を使って導くことができます。
複素数 x, y のべき乗 \(x^y\) は次式で求めることができます。
関数 exp と log は複素数に対応しています。べき乗も演算子 ** で求めることができます。簡単な例を示しましょう。
ghci> pi 3.141592653589793 ghci> exp (0.0 :+ (pi / 4)) 0.7071067811865476 :+ 0.7071067811865475 ghci> exp (0.0 :+ (pi / 2)) 6.123233995736766e-17 :+ 1.0 ghci> exp (0.0 :+ pi) (-1.0) :+ 1.2246467991473532e-16 ghci> exp (1.0 :+ 1.0) 1.4686939399158851 :+ 2.2873552871788423 ghci> log (1.0 :+ 1.0) 0.3465735902799727 :+ 0.7853981633974483 ghci> log (1.0 :+ 0.0) 0.0 :+ 0.0 ghci> log (0.0 :+ 1.0) 0.0 :+ 1.5707963267948966 ghci> log (1.0 :+ (-1.0)) 0.3465735902799727 :+ (-0.7853981633974483) ghci> log (1e300 :+ 1e300) 691.1221014884936 :+ 0.7853981633974483 ghci> (1.0 :+ 1.0) ** 0 1.0 :+ 0.0 ghci> (1.0 :+ 1.0) ** 1 1.0000000000000002 :+ 1.0 ghci> (1.0 :+ 1.0) ** 2 1.2246467991473532e-16 :+ 2.0 ghci> (1.0 :+ 1.0) ** 3 (-2.0) :+ 2.0000000000000004 ghci> (1.0 :+ 1.0) ** (1.0 :+ 1.0) 0.2739572538301211 :+ 0.5837007587586147 ghci> (1.0 :+ 2.0) ** (3.0 :+ 4.0) 0.129009594074467 :+ 3.392409290517014e-2
関数 \(\log z \ (z = x + iy)\) は負の実軸 (\(-\infty \lt x \lt 0\)) において、x + 0.0i と x - 0.0i では値が異なります。
ghci> log ((-1.0) :+ 0.0) 0.0 :+ 3.141592653589793 ghci> log ((-1.0) :+ (-0.0)) 0.0 :+ (-3.141592653589793) ghci> log ((-1e300) :+ 0.0) 690.7755278982137 :+ 3.141592653589793 ghci> log ((-1e300) :+ (-0.0)) 690.7755278982137 :+ (-3.141592653589793)
このように、関数 \(\log z\) は負の実軸上で 2 つの値を持ちます。数学では値を一つ返す関数を「一価関数」、複数の値を返す関数を「多価関数」といいます。ここで、定義域を制限することで多価関数を一価関数にみなすことを考えます。関数 log z の場合、負の実軸を定義域から取り除けば、\(\log z\) を一価関数とみなすことができるわけです。
参考 URL 8 によると、この取り除いた領域を branch cut と呼ぶそうです。プログラミングでは branch cut を定義域から取り除くのではなく、その領域では不連続な関数とするそうです。参考文献 1 では「分枝切断線」、Python のドキュメントでは「分枝切断」と記述されています。本稿では branch cut を「分枝切断」と記述することにします。
プログラミング言語の場合、0.0 と -0.0 を区別する処理系であれば、Haskell のように 2 つの値を区別することができます。0.0 と -0.0 を区別しない処理系では、偏角 \(\theta\) の範囲を \(-\pi \lt \theta \leq \pi\) に制限することで、\(\log z\) の返り値を (\(-\pi\) を取り除いて) 一つにすることができます。
複素数の三角関数の定義は、オイラーの公式から導かれる式の \(\theta\) を複素数 \(z\) に変えたものになります。
\(\sin z, \cos z\) に純虚数 \(ix\) を与えると双曲線関数 (\(\sinh x, \cosh x\)) になります。
これに三角関数の加法定理 [*1] を使うと次の式が導かれます。
Haskell の三角関数 (sin, cos, tan) は複素数にも対応しています。簡単な実行例を示します。
ghci> a = [0.0 :+ 1.0, 0.0 :+ (-1.0), 1.0 :+ 1.0, 1.0 :+ (-1.0)] ghci> a [0.0 :+ 1.0,0.0 :+ (-1.0),1.0 :+ 1.0,1.0 :+ (-1.0)] ghci> map sin a [0.0 :+ 1.1752011936438014, 0.0 :+ (-1.1752011936438014), 1.2984575814159773 :+ 0.6349639147847361, 1.2984575814159773 :+ (-0.6349639147847361)] ghci> map (magnitude . sin) a [1.1752011936438014,1.1752011936438014,1.4453965766582495,1.4453965766582495] ghci> map cos a [1.5430806348152437 :+ (-0.0), 1.5430806348152437 :+ 0.0, 0.8337300251311491 :+ (-0.9888977057628651), 0.8337300251311491 :+ 0.9888977057628651] ghci> map (magnitude . cos) a [1.5430806348152437,1.5430806348152437,1.2934544550420957,1.2934544550420957] ghci> map tan a [0.0 :+ 0.7615941559557649, 0.0 :+ (-0.7615941559557649), 0.2717525853195117 :+ 1.0839233273386946, 0.2717525853195117 :+ (-1.0839233273386946)] ghci> map (magnitude . tan) a [0.7615941559557649,0.7615941559557649,1.1174700207060704,1.1174700207060704]
複素数の双曲線関数の定義は、実数の定義で引数 x を複素数 z に変えたものになります。
sinh z, cosh z に純虚数 ix を与えると三角関数 (sin x, cos x) になります。
これに双曲線関数の加法定理を使うと、次の式が導かれます。
Haskell の双曲線関数 (sinh, cosh, tanh) は複素数に対応しています。簡単な使用例を示します。
ghci> a [0.0 :+ 1.0,0.0 :+ (-1.0),1.0 :+ 1.0,1.0 :+ (-1.0)] ghci> map sinh a [0.0 :+ 0.8414709848078965, 0.0 :+ (-0.8414709848078965), 0.6349639147847361 :+ 1.2984575814159773, 0.6349639147847361 :+ (-1.2984575814159773)] ghci> map cosh a [0.5403023058681398 :+ 0.0, 0.5403023058681398 :+ (-0.0), 0.8337300251311491 :+ 0.9888977057628651, 0.8337300251311491 :+ (-0.9888977057628651)] ghci> map tanh a [0.0 :+ 1.557407724654902, 0.0 :+ (-1.557407724654902), 1.0839233273386946 :+ 0.2717525853195117, 1.0839233273386946 :+ (-0.2717525853195117)]
複素数 z の平方根は次の式で求めることができます。
式 (1) を平方根の主値といいます。角度は \(2\pi\) を足すと同じ角度になるので、式 (2) がもう一つの解になります。三角関数の半角の公式を使うと、式 (1) から次の式が導かれます。
式 (1) を平方根の主値といいます。角度は \(2\pi\) を足すと同じ角度になるので、式 (2) がもう一つの解になります。三角関数の半角の公式を使うと、式 (1) から次の式が導かれます。
Haskell の sqrt は複素数にも対応しています。簡単な実行例を示します。
ghci> sqrt (1.0 :+ 0.0) 1.0 :+ 0.0 ghci> sqrt (2.0 :+ 0.0) 1.4142135623730951 :+ 0.0 ghci> sqrt (3.0 :+ 0.0) 1.7320508075688772 :+ 0.0 ghci> sqrt ((-1.0) :+ 0.0) 0.0 :+ 1.0 ghci> sqrt ((-2.0) :+ 0.0) 0.0 :+ 1.4142135623730951 ghci> sqrt ((-3.0) :+ 0.0) 0.0 :+ 1.7320508075688772 ghci> a [0.0 :+ 1.0,0.0 :+ (-1.0),1.0 :+ 1.0,1.0 :+ (-1.0)] ghci> map sqrt a [0.7071067811865476 :+ 0.7071067811865475, 0.7071067811865476 :+ (-0.7071067811865475), 1.09868411346781 :+ 0.45508986056222733, 1.09868411346781 :+ (-0.45508986056222733)] ghci> map (**2) (map sqrt a) [6.123233995736766e-17 :+ 1.0, 6.123233995736766e-17 :+ (-1.0), 1.0 :+ 0.9999999999999998, 1.0 :+ (-0.9999999999999998)]
\(\sqrt x\) は \(\log x\) と同じ分枝切断を持っています。x を負の整数とすると sqrt(x) の解は \(i \sqrt x\) になりますが、もうひとつ \(-i \sqrt x\) という解があります。
ghci> sqrt ((-2.0) :+ 0.0) 0.0 :+ 1.4142135623730951 ghci> sqrt ((-2.0) :+ (-0.0)) 0.0 :+ 1.4142135623730951 ghci> sqrt ((-1e300) :+ 0.0) 0.0 :+ 1.0e150 ghci> sqrt ((-1e300) :+ (-0.0)) 0.0 :+ 1.0e150
M.Hiroi が使っているバージョン (GHC version 8.8.4) では、sqrt の分枝切断に不具合がある、もしくは負のゼロには対応していないのかもしれません。新しいバージョンでは修正されているかもしれません。
三角関数の逆関数を「逆三角関数 (inverse trigonometric function)」といいます。以下に Haskell に用意されている逆三角関数を示します。
ここでは引数 x を実数とします。asin x は引数 x が与えられたとき sin w = x となる角度 w を求めます。同様に acos x は cos w = x となる角度 w を、atan x は tan x = w となる角度 w を求めます。三角関数には周期性があるので、上式を満たす角度 w は無数に存在します。つまり、逆三角関数の返り値は無数にあることになりますが、通常は一つの値を返すように範囲を制限します。これを「主値」といいます。
逆三角関数の主値を以下に示します。
本ページでは、数式の表示に JavaScript のライブラリ MathJax を使っています。MathJax では、逆三角関数を arcsin, arccos, arctan と表示します。
簡単な実行例を示します。
ghci> map asin [-1.0, -0.5, 0.0, 0.5, 1.0] [-1.5707963267948966, -0.5235987755982989, 0.0, 0.5235987755982989, 1.5707963267948966] ghci> map acos [-1.0, -0.5, 0.0, 0.5, 1.0] [3.141592653589793, 2.0943951023931957, 1.5707963267948966, 1.0471975511965979, 0.0] ghci> map atan [-1e100, -1.0, 0.0, 1.0, 1e100] [-1.5707963267948966, -0.7853981633974483, 0.0, 0.7853981633974483, 1.5707963267948966]
Haskell には 2 引数の関数 atan2 y x も用意されています。これは他のプログラミング言語、たとえばC言語の数学関数 atan2 と同じです。
atan2 y x => 角度 (ラジアン)
引数 x, y は実数です。atan2 は直交座標系においてベクトル (x, y) と x 軸との角度を求める関数です。複素平面で考えると、複素数 \(x + iy\) の偏角 \(\theta\) を求めることと同じです。返り値 (角度 \(\theta\)) の範囲は \(-\pi \leq \theta \leq \pi\) になります。
簡単な実行例を示します。
ghci> map (\(x, y) -> atan2 y x) [(-1.0, 0.0),(-1.0, 1.0),(0.0, 1.0),(1.0, 1.0), (1.0, 0.0),(1.0, -1.0),(0.0, -1.0),(-1.0, -1.0),(-1.0, -0.0)] [3.141592653589793, 2.356194490192345, 1.5707963267948966, 0.7853981633974483, 0.0, -0.7853981633974483, -1.5707963267948966, -2.356194490192345, -3.141592653589793]
複素数の逆三角関数の定義は、複素数の三角関数の定義から導くことができます。\(\arcsin z\) の定義は次のようになります。
\(\arccos z, \arctan z\) は定義だけを示します。
asin, acos, atan は次に示す分枝切断を持っています。
Haskell の逆三角関数 (asin, acos, atan) は複素数に対応しています。簡単な実行例を示します。
ghci> a [0.0 :+ 1.0,0.0 :+ (-1.0),1.0 :+ 1.0,1.0 :+ (-1.0)] ghci> map asin a [0.0 :+ 0.8813735870195428, 0.0 :+ (-0.8813735870195429), 0.6662394324925153 :+ 1.0612750619050355, 0.6662394324925153 :+ (-1.0612750619050357)] ghci> map (sin . asin) a [0.0 :+ 0.9999999999999997, 0.0 :+ (-1.0), 1.0 :+ 0.9999999999999998, 1.0000000000000002 :+ (-1.0)] ghci> asin(2.0 :+ 0.0) 1.5707963267948966 :+ (-1.3169578969248166) ghci> asin(2.0 :+ (-0.0)) 1.5707963267948966 :+ (-1.3169578969248166) ghci> asin((-4.0) :+ 0.0) (-1.5707963267948966) :+ 2.0634370688955617 ghci> asin((-4.0) :+ (-0.0)) (-1.5707963267948966) :+ 2.0634370688955617 ghci> map acos a [1.5707963267948966 :+ (-0.8813735870195429), 1.5707963267948966 :+ 0.8813735870195428, 0.9045568943023814 :+ (-1.0612750619050357), 0.9045568943023814 :+ 1.0612750619050355] ghci> map (cos . acos) a [8.659560562354932e-17 :+ 1.0, 8.659560562354932e-17 :+ (-0.9999999999999997), 0.9999999999999999 :+ 1.0, 0.9999999999999998 :+ (-0.9999999999999998)] ghci> acos(2.0 :+ 0.0) 0.0 :+ 1.3169578969248164 ghci> acos(2.0 :+ (-0.0)) 0.0 :+ 1.3169578969248164 ghci> acos((-4.0) :+ 0.0) 3.141592653589793 :+ (-2.0634370688955608) ghci> acos((-4.0) :+ (-0.0)) 3.141592653589793 :+ (-2.0634370688955608) ghci> map atan a [NaN :+ NaN, NaN :+ NaN, 1.0172219678978514 :+ 0.4023594781085251, 1.0172219678978514 :+ (-0.4023594781085249)] ghci> map (tan . atan) a [NaN :+ NaN, NaN :+ NaN, 1.0 :+ 1.0000000000000002, 1.0000000000000004 :+ (-0.9999999999999999)] ghci> atan (0.0 :+ 2.0) 1.5707963267948966 :+ 0.5493061443340547 ghci> atan ((-0.0) :+ 2.0) 1.5707963267948966 :+ 0.5493061443340547 ghci> atan (0.0 :+ (-4.0)) (-1.5707963267948966) :+ (-0.25541281188299514) ghci> atan ((-0.0) :+ (-4.0)) (-1.5707963267948966) :+ (-0.25541281188299514)
M.Hiroi が使っているバージョン (GHC version 8.8.4) では、逆三角関数の分枝切断に不具合がある、もしくは負のゼロには対応していないのかもしれません。新しいバージョンでは修正されているかもしれません。
双曲線関数の逆関数を「逆双曲線関数 (inverse hyperbolic function)」といいます。Haskell に用意されている逆双曲線関数には asinh, acosh, atanh があります。MathJax では逆双曲線関数を \(\sinh^{-1} x, \cosh^{-1} x, \tanh^{-1} x \) で表します。双曲線関数と逆双曲線関数の定義域と値域を示します。
x と y は実数です。x = cosh y の逆関数 y = acosh x を満たす y の値は 2 つありますが、ここでは \(y \geq 0\) を主値として選ぶことにします。
逆双曲線関数の定義は双曲線関数の定義から導くことができます。
関数 \(\tanh^{-1} x\) を使うと、次の関係式から \(\sinh^{-1} x, \ \cosh^{-1} x\) を求めることができます。
簡単な実行例を示します。
ghci> map asinh [1.5, 1.0, 0.5, 0.0, -0.5, -1.0, -1.5] [1.1947632172871094, 0.881373587019543, 0.48121182505960347, 0.0, -0.48121182505960347, -0.881373587019543, -1.1947632172871094] ghci> map (sinh . asinh) [1.5, 1.0, 0.5, 0.0, -0.5, -1.0, -1.5] [1.5000000000000004, 1.0, 0.5, 0.0, -0.5, -1.0, -1.5000000000000004] julia> for x = [1.5, 1.0, 0.5, 0.0, -0.5, -1.0, -1.5] b = asinh(x); println(b); println(sinh(b)) end 1.1947632172871094 1.5000000000000002 0.881373587019543 1.0 0.48121182505960347 0.5 0.0 0.0 -0.48121182505960347 -0.5 -0.881373587019543 -1.0 -1.1947632172871094 -1.5000000000000002 ghci> map acosh [1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0] [0.0, 0.9624236501192069, 1.3169578969248166, 1.566799236972411, 1.762747174039086, 1.9248473002384139, 2.0634370688955608] ghci> map (cosh . acosh) [1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0] [1.0, 1.5, 1.9999999999999998, 2.5, 3.0000000000000004, 3.5000000000000004, 4.000000000000001] ghci> map atanh [-0.75, -0.5, -0.25, 0.0, 0.25, 0.5, 0.75] [-0.9729550745276566, -0.5493061443340548, -0.25541281188299536, 0.0, 0.25541281188299536, 0.5493061443340548, 0.9729550745276566] ghci> map (tanh . atanh) [-0.75, -0.5, -0.25, 0.0, 0.25, 0.5, 0.75] [-0.75, -0.49999999999999994, -0.25, 0.0, 0.25, 0.49999999999999994, 0.75]
複素数の逆双曲線関数の定義は、実数の定義で引数 x を複素数 z に変えたものになります。
参考文献, URL 7 によると、\(\cosh^{-1} z\) を式 (1) でプログラムすると「分枝切断線」が複雑になるため、他の式 (たとえば (2) など) でプログラムする処理系が多いようです。ちなみに、ANSI Common Lisp では \(\cosh^{-1} z\) を次の式で定義しています。
asinh, acosh, atanh は次に示す分枝切断を持っています。
Haskell の逆双曲線関数 (asinh, acosh, atanh) は複素数に対応しています。簡単な実行例を示します。
ghci> a [0.0 :+ 1.0,0.0 :+ (-1.0),1.0 :+ 1.0,1.0 :+ (-1.0)] ghci> map asinh a [0.0 :+ 1.5707963267948966, 0.0 :+ (-1.5707963267948966), 1.0612750619050357 :+ 0.6662394324925153, 1.0612750619050357 :+ (-0.6662394324925153)] ghci> map (sinh . asinh) a [0.0 :+ 1.0, 0.0 :+ (-1.0), 1.0 :+ 1.0000000000000002, 1.0 :+ (-1.0000000000000002)] ghci> asinh(0.0 :+ 2.0) 1.3169578969248166 :+ 1.5707963267948966 ghci> asinh((-0.0) :+ 2.0) 1.3169578969248166 :+ 1.5707963267948966 ghci> asinh(0.0 :+ (-4.0)) (-2.0634370688955617) :+ (-1.5707963267948966) ghci> asinh((-0.0) :+ (-4.0)) (-2.0634370688955617) :+ (-1.5707963267948966) ghci> map acosh a [0.8813735870195429 :+ 1.5707963267948966, 0.8813735870195429 :+ (-1.5707963267948966), 1.0612750619050357 :+ 0.9045568943023814, 1.0612750619050357 :+ (-0.9045568943023814)] ghci> map (cosh . acosh) a [8.659560562354932e-17 :+ 1.0, 8.659560562354932e-17 :+ (-1.0), 0.9999999999999999 :+ 1.0, 0.9999999999999999 :+ (-1.0)] ghci> acosh(0.0 :+ 0.0) 0.0 :+ 1.5707963267948966 ghci> acosh(0.0 :+ (-0.0)) 0.0 :+ 1.5707963267948966 ghci> acosh((-4.0) :+ 0.0) 2.0634370688955608 :+ 3.141592653589793 ghci> acosh((-4.0) :+ (-0.0)) 2.0634370688955608 :+ 3.141592653589793 ghci> map atanh a [0.0 :+ 0.7853981633974483, 0.0 :+ (-0.7853981633974483), 0.4023594781085251 :+ 1.0172219678978514, 0.4023594781085251 :+ (-1.0172219678978514)] ghci> map (tanh . atanh) a [0.0 :+ 0.9999999999999998, 0.0 :+ (-0.9999999999999998), 1.0000000000000002 :+ 1.0, 1.0000000000000002 :+ (-1.0)] ghci> atanh(2.0 :+ 0.0) 0.5493061443340549 :+ (-1.5707963267948966) ghci> atanh(2.0 :+ (-0.0)) 0.5493061443340549 :+ (-1.5707963267948966) ghci> atanh((-4.0) :+ 0.0) (-0.25541281188299536) :+ 1.5707963267948966 ghci> atanh((-4.0) :+ (-0.0)) (-0.25541281188299536) :+ 1.5707963267948966
M.Hiroi が使っているバージョン (GHC version 8.8.4) では、逆双曲線関数の分枝切断に不具合がある、もしくは負のゼロには対応していないのかもしれません。新しいバージョンでは修正されているかもしれません。