近年、多くのプログラミング言語で「複素数 (complex number)」がサポートされるようになりました。たとえば、C言語では 1999 年に発行された規格 C99 で複素数型が導入されました。Go 言語や Python でも複素数型をサポートしていますし、複素数用の標準ライブラリを用意している言語 (C++, Ruby, Haskell など) も多くあります。
他の言語では、FORTRAN や Common Lisp が昔から複素数型をサポートしています。Common Lisp の場合、基本的な数学関数でも複素数を適用できるのであれば、引数に複素数を渡して計算することができます。もちろん、Julia でも複素数を扱うことができます。今回は Julia の複素数についてまとめてみました。
Julia の数は大きく分けると、整数 (integer)、実数 (float)、有理数 (rational)、複素数 (complex) の 4 種類があります。Julia は BigInt (多倍長整数) をサポートしているので、BigInt を使えばメモリの許す限り任意の精度で扱うことができます。有理数 (分数) は分子と分母を整数で保持していますが、BigInt を使えば任意の精度で扱うことができます。
実数は浮動小数点数 (floating point number) として表現されます。浮動小数点数には IEEE 754 という標準仕様があり、近代的なプログラミング言語のほとんどは、IEEE 754 に準拠した浮動小数点数をサポートしています。浮動小数点数はすべての小数を正確に表現することはできません。このため、実数は近似的 (不正確) な値になります。
IEEE 754 には通常の数値以外にも、負のゼロ (-0.0)、正負の無限大 (∞, -∞)、NaN (Not a Number, 非数) といった値が定義されています。これらの値は Julia でも取り扱うことができます。負のゼロは -0.0、正負の無限大は Inf と -Inf、NaN は NaN として定義されています。
一般に、無限大は値のオーバーフロー、ゼロ除算 (数値 / 0.0)、数学関数の計算結果 (たとえば log(0.0)) などで発生します。なお、浮動小数点数のゼロ除算でエラー (例外) を送出する処理系 (たとえば Python など) もあります。
簡単な実行例を示します。
julia> Inf Inf julia> -Inf -Inf julia> 1e308 1.0e308 julia> 1e309 ERROR: syntax: overflow in numeric constant "1e309" julia> 1e308 * 2 Inf julia> -1e308 -1.0e308 julia> -1e308 * 2 -Inf julia> 1.0 / 0.0 Inf julia> -1.0 / 0.0 -Inf
Julia の場合、無限大の判定は関数 isinf() を使います。
julia> isinf(Inf) true julia> isinf(-Inf) true julia> isinf(1.234) false
無限大は他の数値と比較したり演算することもできますが、結果が NaN になることもあります。
julia> Inf == Inf true julia> Inf == -Inf false julia> -Inf < Inf true julia> Inf < -Inf false julia> Inf > 0 true julia> -Inf < 0 true julia> Inf < 0 false julia> -Inf > 0 false julia> Inf + 10 Inf julia> Inf - 10 Inf julia> Inf * 10 Inf julia> Inf / 10 Inf julia> Inf + Inf Inf julia> Inf * Inf Inf julia> Inf / Inf NaN julia> Inf - Inf NaN julia> Inf + -Inf NaN julia> Inf * 0.0 NaN
負のゼロ (-0.0) は、計算結果が負の極めて小さな値でアンダーフローになったとき発生します。また、正の値を負の無限大で除算する、負の値を正の無限大で除算する、負の値と 0.0 を乗算しても -0.0 が得られます。
julia> -1e-323 -1.0e-323 julia> -1e-324 -0.0 julia> -1e-323 / 2 -5.0e-324 julia> -1e-323 / 4 -0.0 julia> 1.0 / -Inf -0.0 julia> -1.0 / Inf -0.0 julia> -1.0 * 0.0 -0.0
標準 (IEEE 754) では、演算子 (Julia では ==) による 0.0 と -0.0 の比較は等しいと判定されます。関数 isequal() を使うと、0.0 と -0.0 を区別することができます。
julia> 0.0 == -0.0 true julia> -0.0 == 0.0 true julia> 0.0 != -0.0 false julia> isequal(0.0, -0.0) false julia> isequal(-0.0, -0.0) true
なお、-0.0 は数学関数 (2 引数の関数 atan [C言語の数学関数 atan2 と同じ] など) や複素数の演算処理などで使われます。
julia> sqrt(0.0) 0.0 julia> sqrt(-0.0) -0.0 julia> atan(0.0, -1.0) 3.141592653589793 julia> atan(-0.0, -1.0) -3.141592653589793
NaN は数ではないことを表す特別な値 (非数) です。一般的には 0.0 / 0.0 といった不正な演算を行うと、その結果は NaN になります。
julia> NaN NaN julia> NaN / NaN NaN julia> Inf / Inf NaN julia> 0.0 / 0.0 NaN
Julia の場合、NaN は関数 isnan() で判別することができます。関数 isfinite は引数が無限大でも NaN でもなければ真を返します。標準 (IEEE 754) では NaN == NaN を偽と判定しますが、isequal(NaN, NaN) は真を返します。
julia> isnan(NaN) true julia> isnan(Inf) false julia> isnan(1.234) false julia> isfinite(NaN) false julia> isfinite(Inf) false julia> isfinite(1.234) true julia> NaN == NaN false julia> NaN != NaN true julia> isequal(NaN, NaN) true
数学では複素数 \(z\) を \(x + yi\) と表記します。x を実部、y を虚部、i を虚数単位といいます。虚数単位は 2 乗すると -1 になる数です。実部と虚部の 2 つの数値を格納するデータ構造を用意すれば、プログラミング言語でも複素数を表すことができます。Julia は複素数 \(x + yi\) を x + yim と表記します。実部 x を省略すると x は 0 に、虚部 y を省略して im だけにすると y は 1 になります。
複素数のデータ型名は Complex です。
複素数はコンストラクタ complex(x, y) で生成することもできます。
complex(x, y)
x が実部で、y が虚部を表します。y を省略すると虚部は 0 になります。複素数 z の実部は関数 real で、虚部は関数 imag で取得することができます。複素数の虚部の符号を反転することを「複素共役」といいます。複素共役は関数 conj() で求めることができます。
簡単な例を示しましょう。
julia> 1 + 2im 1 + 2im julia> typeof(1 + 2im) Complex{Int64} julia> 3.0 + 4.0im 3.0 + 4.0im julia> typeof(3.0 + 4.0im) ComplexF64 (alias for Complex{Float64}) julia> 2.0im 0.0 + 2.0im julia> 1.0 + im 1.0 + 1.0im julia> complex(1.234, 5.678) 1.234 + 5.678im julia> complex(1.234) 1.234 + 0.0im julia> a = complex(1.234, 5.678) 1.234 + 5.678im julia> real(a) 1.234 julia> imag(a) 5.678 julia> conj(a) 1.234 - 5.678im julia> -1.0im -0.0 - 1.0im julia> 1.0 - 0.0im 1.0 - 0.0im julia> 1.0 + 0.0im 1.0 + 0.0im julia> -0.0 + 1.0im 0.0 + 1.0im julia> -0.0 - 1.0im -0.0 - 1.0im julia> complex(-0.0, 1.0) -0.0 + 1.0im
Julia で -1.0im と入力すると、実部は負のゼロになるようです。また、-0.0 + yim (y > 0) のとき、0.0 + yim と解釈されるようです。実部に負のゼロをセットする場合は complex() を使ったほうが良いでしょう。
複素数は極形式 \(z = |z|(\cos \theta + i \sin \theta)\) で表すことができます。このとき、\(|z|\) を絶対値、\(\theta\) を偏角といいます。絶対値は関数 abs() で求めることができます。偏角は複素平面において正の実軸とベクトル (x, y) との角度を表します。偏角を求めるには関数 angle を使います。angle の返り値 \(\theta\) は \(-\pi \leq \theta \leq \pi \) (\(\pi\) : 円周率) です。 このほかに、絶対値の 2 乗を返す関数 abs2() や、絶対値が 1 で偏角が x の複素数を返す関数 cis(x) もあります。cis は cos + i sin の略です。
簡単な例を示しましょう。
julia> a = 1.0 + 1.0im 1.0 + 1.0im julia> abs(a) 1.4142135623730951 julia> abs2(a) 2.0 julia> angle(a) 0.7853981633974483 julia> pi π = 3.1415926535897... julia> pi / 4 0.7853981633974483 julia> cis(pi/4) 0.7071067811865476 + 0.7071067811865475im julia> angle(1.0 + 0.0im) 0.0 julia> angle(1.0 + 1.0im) 0.7853981633974483 julia> angle(0.0 + 1.0im) 1.5707963267948966 julia> angle(-1.0 + 1.0im) 2.356194490192345 julia> angle(-1.0 + 0.0im) 3.141592653589793 julia> angle(1.0 - 1.0im) -0.7853981633974483 julia> angle(0.0 - 1.0im) -1.5707963267948966 julia> angle(-1.0 - 1.0im) -2.356194490192345 julia> angle(-1.0 - 0.0im) -3.141592653589793
Julia の場合、-1.0+0.0im の偏角 \(\theta\) は \(\pi\) になり、-1.0-0.0im の偏角は \(-\pi\) になります。ゼロと負のゼロを区別しないプログラミング言語では、偏角 \(\theta\) の範囲を \(-\pi \lt \theta \leq \pi\) に制限して、-1.0 + 0.0im (== -1.0 - 0.0im) の偏角を \(\pi\) とします。
複素数の四則演算は次のようになります。
これらの演算は Julia の演算子 +, -, * , / で行うことができます。複素数の場合、大小の比較演算は使えませんが、等値の判定は演算子 == や != で行うことができます。簡単な例を示しましょう。
julia> a = 1.0 + 2.0im 1.0 + 2.0im julia> b = 3.0 + 4.0im 3.0 + 4.0im julia> a + b 4.0 + 6.0im julia> a - b -2.0 - 2.0im julia> a * b -5.0 + 10.0im julia> a / b 0.44 + 0.08im julia> a == a true julia> a == b false julia> a != a false julia> a != b true
実部と虚部の値は Inf, -Inf, NaN になることもあります。
julia> complex(Inf, Inf) Inf + Inf*im julia> complex(Inf, NaN) Inf + NaN*im julia> NaN + Inf * im NaN + Inf*im julia> NaN + NaN * im NaN + NaN*im julia> (1e300 + 1e300im) * (1e300 + 1e300im) NaN + Inf*im julia> isinf(1+Inf*im) true julia> isfinite(1+Inf*im) false julia> isfinite(1+2im) true julia> isnan(1+Inf*im) false julia> isnan(NaN+Inf*im) true
isinf() は実部または虚部が無限大であれば真を返します。isnan() は実部または虚部が NaN であれば真を返します。isfinite() は実部と虚部が有限な値であれば真を返します。
複素数を引数にとる指数関数はオイラー (Euler) の公式から導くことができます。
複素数の対数関数は複素数 z を絶対値 \(|z|\) と偏角 \(\theta\) を使って導くことができます。
複素数 x, y のべき乗 \(x^y\) は次式で求めることができます。
関数 exp と log は複素数に対応しています。べき乗も演算子 ^ で求めることができます。簡単な例を示しましょう。
julia> exp(0.0+pi/4*im) 0.7071067811865476 + 0.7071067811865475im julia> exp(0.0+pi/2*im) 6.123233995736766e-17 + 1.0im julia> exp(0.0+pi*im) -1.0 + 1.2246467991473532e-16im julia> exp(0.0-pi*im) -1.0 - 1.2246467991473532e-16im julia> exp(1.0+1.0im) 1.4686939399158851 + 2.2873552871788423im julia> log(1.0+1.0im) 0.34657359027997264 + 0.7853981633974483im julia> log(1.0+0.0im) 0.0 + 0.0im julia> log(0.0+1.0im) 0.0 + 1.5707963267948966im julia> log(1.0-1.0im) 0.34657359027997264 - 0.7853981633974483im julia> log(1e300 + 1e300im) 691.1221014884936 + 0.7853981633974483im julia> (1.0 + 1.0im) ^ 0 1.0 + 0.0im julia> (1.0 + 1.0im) ^ 1 1.0 + 1.0im julia> (1.0 + 1.0im) ^ 2 0.0 + 2.0im julia> (1.0 + 1.0im) ^ 3 -2.0 + 2.0im julia> (1.0 + 2.0im) ^ (3.0 + 4.0im) 0.12900959407446697 + 0.03392409290517014im julia> (1.0 + 1.0im) ^ (1.0 + 1.0im) 0.2739572538301211 + 0.5837007587586147im
関数 \(\log z \ (z = x + iy)\) は負の実軸 (\(-\infty \lt x \lt 0\)) において、x + 0.0im と x - 0.0im では値が異なります。
julia> log(-1.0+0.0im) 0.0 + 3.141592653589793im julia> log(-1.0-0.0im) 0.0 - 3.141592653589793im julia> log(-1e300+0.0im) 690.7755278982137 + 3.141592653589793im julia> log(-1e300-0.0im) 690.7755278982137 - 3.141592653589793im
このように、関数 \(\log z\) は負の実軸上で 2 つの値を持ちます。数学では値を一つ返す関数を「一価関数」、複数の値を返す関数を「多価関数」といいます。ここで、定義域を制限することで多価関数を一価関数にみなすことを考えます。関数 \(\log z\) の場合、負の実軸を定義域から取り除けば、\(\log z\) を一価関数とみなすことができるわけです。
参考 URL 8 『逆双曲線関数と逆三角関数の branch cut | 雑記帳』によると、この取り除いた領域を branch cut と呼ぶそうです。プログラミングでは branch cut を定義域から取り除くのではなく、その領域では不連続な関数とするそうです。参考文献 1 『COMMON LISP 第 2 版』では「分枝切断線」、Python のドキュメントでは「分枝切断」と記述されています。本稿では branch cut を「分枝切断」と記述することにします。
プログラミング言語の場合、0.0 と -0.0 を区別する処理系であれば、Julia のように 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] を使うと次の式が導かれます。
Julia の三角関数 (sin, cos, tan) は複素数にも対応しています。簡単な実行例を示します。
julia> a = [0.0+1.0im, 0.0-1.0im, 1.0+1.0im, 1.0-1.0im] 4-element Vector{ComplexF64}: 0.0 + 1.0im 0.0 - 1.0im 1.0 + 1.0im 1.0 - 1.0im julia> for x = a println(sin(x)); println(abs(sin(x))) end 0.0 + 1.1752011936438014im 1.1752011936438014 0.0 - 1.1752011936438014im 1.1752011936438014 1.2984575814159773 + 0.6349639147847361im 1.4453965766582495 1.2984575814159773 - 0.6349639147847361im 1.4453965766582495 julia> for x = a println(cos(x)); println(abs(cos(x))) end 1.5430806348152437 - 0.0im 1.5430806348152437 1.5430806348152437 + 0.0im 1.5430806348152437 0.8337300251311491 - 0.9888977057628651im 1.2934544550420957 0.8337300251311491 + 0.9888977057628651im 1.2934544550420957 julia> for x = a println(tan(x)); println(abs(tan(x))) end 0.0 + 0.7615941559557649im 0.7615941559557649 0.0 - 0.7615941559557649im 0.7615941559557649 0.27175258531951174 + 1.0839233273386946im 1.1174700207060704 0.27175258531951174 - 1.0839233273386946im 1.1174700207060704
複素数の双曲線関数の定義は、実数の定義で引数 x を複素数 z に変えたものになります。
sinh z, cosh z に純虚数 ix を与えると三角関数 (sin x, cos x) になります。
これに双曲線関数の加法定理を使うと、次の式が導かれます。
Julia の双曲線関数 (sinh, cosh, tanh) は複素数に対応しています。簡単な使用例を示します。
julia> a 4-element Vector{ComplexF64}: 0.0 + 1.0im 0.0 - 1.0im 1.0 + 1.0im 1.0 - 1.0im julia> for x = a println(sinh(x)) end 0.0 + 0.8414709848078965im 0.0 - 0.8414709848078965im 0.6349639147847361 + 1.2984575814159773im 0.6349639147847361 - 1.2984575814159773im julia> for x = a println(cosh(x)) end 0.5403023058681398 + 0.0im 0.5403023058681398 - 0.0im 0.8337300251311491 + 0.9888977057628651im 0.8337300251311491 - 0.9888977057628651im julia> for x = a println(tanh(x)) end 0.0 + 1.5574077246549023im 0.0 - 1.5574077246549023im 1.0839233273386946 + 0.27175258531951174im 1.0839233273386946 - 0.27175258531951174im
複素数 \(z\) の平方根は次の式で求めることができます。
式 (1) を平方根の主値といいます。角度は \(2\pi\) を足すと同じ角度になるので、式 (2) がもう一つの解になります。三角関数の半角の公式を使うと、式 (1) から次の式が導かれます。
Julia の sqrt は複素数にも対応しています。簡単な実行例を示します。
julia> sqrt(1.0 + 0.0im) 1.0 + 0.0im julia> sqrt(2.0 + 0.0im) 1.4142135623730951 + 0.0im julia> sqrt(3.0 + 0.0im) 1.7320508075688772 + 0.0im julia> sqrt(-1.0 + 0.0im) 0.0 + 1.0im julia> sqrt(-2.0 + 0.0im) 0.0 + 1.4142135623730951im julia> sqrt(-3.0 + 0.0im) 0.0 + 1.7320508075688772im julia> a 4-element Vector{ComplexF64}: 0.0 + 1.0im 0.0 - 1.0im 1.0 + 1.0im 1.0 - 1.0im julia> for x = a b = sqrt(x); println(b); println(b * b) end 0.7071067811865476 + 0.7071067811865475im 2.220446049250313e-16 + 1.0im 0.7071067811865476 - 0.7071067811865475im 2.220446049250313e-16 - 1.0im 1.09868411346781 + 0.45508986056222733im 1.0000000000000002 + 1.0im 1.09868411346781 - 0.45508986056222733im 1.0000000000000002 - 1.0im
\(\sqrt x\) は \(\log x\) と同じ分枝切断を持っています。x を負の整数とすると sqrt(x) の解は \(i \sqrt x\) になりますが、もうひとつ \(-i \sqrt x\) という解があります。
julia> sqrt(-2.0 + 0.0im) 0.0 + 1.4142135623730951im julia> sqrt(-2.0 - 0.0im) 0.0 - 1.4142135623730951im julia> sqrt(-1e300 + 0.0im) 0.0 + 1.0e150im julia> sqrt(-1e300 - 0.0im) 0.0 - 1.0e150im
三角関数の逆関数を「逆三角関数 (inverse trigonometric function)」といいます。以下に Julia にある逆三角関数を示します。
ここでは引数 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 と表示します。
簡単な実行例を示します。
julia> for x = [-1.0, -0.5, 0.0, 0.5, 1.0] println(asin(x)) end -1.5707963267948966 -0.5235987755982989 0.0 0.5235987755982989 1.5707963267948966 julia> for x = [-1.0, -0.5, 0.0, 0.5, 1.0] println(acos(x)) end 3.141592653589793 2.0943951023931957 1.5707963267948966 1.0471975511965979 0.0 julia> for x = [-1e300, -1.0, 0.0, 1.0, 1e300] println(atan(x)) end -1.5707963267948966 -0.7853981633974483 0.0 0.7853981633974483 1.5707963267948966
Julia には 2 引数の関数 atan(y, x) も用意されています。これは他のプログラミング言語、たとえばC言語の数学関数 atan2 と同じです。
atan(y, x) => 角度 (ラジアン)
引数 x, y は実数です。atan は直交座標系においてベクトル (x, y) と x 軸との角度を求める関数です。複素平面で考えると、複素数 \(x + iy\) の偏角 \(\theta\) を求めることと同じです。返り値 (角度 \(\theta\)) の範囲は \(-\pi \leq \theta \leq \pi\) になります。
簡単な実行例を示します。
julia> for (x, y) = [(-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)] println(atan(y, x)) end 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 は次に示す分枝切断を持っています。
Julia の逆三角関数 (asin, acos, atan) は複素数に対応しています。簡単な実行例を示します。
julia> a 4-element Vector{ComplexF64}: 0.0 + 1.0im 0.0 - 1.0im 1.0 + 1.0im 1.0 - 1.0im julia> for x = a b = asin(x); println(b); println(sin(b)) end 0.0 + 0.881373587019543im 0.0 + 1.0im 0.0 - 0.881373587019543im 0.0 - 1.0im 0.6662394324925153 + 1.0612750619050357im 1.0000000000000002 + 1.0im 0.6662394324925153 - 1.0612750619050357im 1.0000000000000002 - 1.0im julia> asin(2.0+0.0im) 1.5707963267948966 + 1.3169578969248166im julia> asin(2.0-0.0im) 1.5707963267948966 - 1.3169578969248166im julia> asin(-4.0+0.0im) -1.5707963267948966 + 2.0634370688955608im julia> asin(-4.0-0.0im) -1.5707963267948966 - 2.0634370688955608im julia> for x = a b = acos(x); println(b); println(cos(b)) end 1.5707963267948966 - 0.881373587019543im 8.659560562354934e-17 + 1.0im 1.5707963267948966 + 0.881373587019543im 8.659560562354934e-17 - 1.0im 0.9045568943023813 - 1.0612750619050357im 1.0000000000000002 + 1.0im 0.9045568943023813 + 1.0612750619050357im 1.0000000000000002 - 1.0im julia> acos(2.0+0.0im) 0.0 - 1.3169578969248166im julia> acos(2.0-0.0im) 0.0 + 1.3169578969248166im julia> acos(-4.0+0.0im) 3.141592653589793 - 2.0634370688955608im julia> acos(-4.0-0.0im) 3.141592653589793 + 2.0634370688955608im julia> for x = a b = atan(x); println(b); println(tan(b)) end 0.0 + Inf*im 0.0 + 1.0im 0.0 - Inf*im 0.0 - 1.0im 1.0172219678978514 + 0.40235947810852507im 1.0 + 1.0im 1.0172219678978514 - 0.40235947810852507im 1.0 - 1.0im julia> atan(complex(0.0, 2.0)) 1.5707963267948966 + 0.5493061443340549im julia> atan(complex(-0.0, 2.0)) -1.5707963267948966 + 0.5493061443340549im julia> atan(complex(0.0, -4.0)) 1.5707963267948966 - 0.2554128118829953im julia> atan(complex(-0.0, -4.0)) -1.5707963267948966 - 0.2554128118829953im
atan() の分枝切断において、-0.0 + 2.0im と入力すると 0.0 + 2.0im と解釈されるので、complex() を使って実部に -0.0 を指定しています。
双曲線関数の逆関数を「逆双曲線関数 (inverse hyperbolic function)」といいます。Julia に用意されている逆双曲線関数には 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\) を求めることができます。
簡単な実行例を示します。
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 julia> for x = [1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0] b = acosh(x); println(b); println(cosh(b)) end 0.0 1.0 0.9624236501192069 1.5000000000000002 1.3169578969248166 1.9999999999999998 1.566799236972411 2.5 1.762747174039086 3.0000000000000004 1.9248473002384139 3.5000000000000004 2.0634370688955608 4.000000000000001 julia> for x = [-0.75, -0.5, -0.25, 0.0, 0.25, 0.5, 0.75] b = atanh(x); println(b); println(tanh(b)) end -0.9729550745276566 -0.75 -0.5493061443340549 -0.5 -0.2554128118829953 -0.24999999999999997 0.0 0.0 0.2554128118829953 0.24999999999999997 0.5493061443340549 0.5 0.9729550745276566 0.75
複素数の逆双曲線関数の定義は、実数の定義で引数 x を複素数 \(z\) に変えたものになります。
参考文献, URL 8 『逆双曲線関数と逆三角関数の branch cut | 雑記帳』によると、\(\cosh^{-1} z\) を式 (1) でプログラムすると「分枝切断線」が複雑になるため、他の式 (たとえば (2) など) でプログラムする処理系が多いようです。ちなみに、ANSI Common Lisp では \(\cosh^{-1} z\) を次の式で定義しています。
\(\sinh^{-1} z, \cosh^{-1} z, \tanh^{-1} z\) は次に示す分枝切断を持っています。
Julia の逆双曲線関数 (asinh, acosh, atanh) は複素数に対応しています。簡単な実行例を示します。
julia> for x = a b = asinh(x); println(b); println(sinh(b)) end 0.0 + 1.5707963267948966im 0.0 + 1.0im 0.0 - 1.5707963267948966im 0.0 - 1.0im 1.0612750619050357 + 0.6662394324925153im 1.0 + 1.0000000000000002im 1.0612750619050357 - 0.6662394324925153im 1.0 - 1.0000000000000002im julia> asinh(complex(0.0, 2.0)) 1.3169578969248166 + 1.5707963267948966im julia> asinh(complex(-0.0, 2.0)) -1.3169578969248166 + 1.5707963267948966im julia> asinh(complex(0.0, -4.0)) 2.0634370688955608 - 1.5707963267948966im julia> asinh(complex(-0.0, -4.0)) -2.0634370688955608 - 1.5707963267948966im julia> for x = a b = acosh(x); println(b); println(cosh(b)) end 0.881373587019543 + 1.5707963267948966im 8.659560562354934e-17 + 1.0im 0.881373587019543 - 1.5707963267948966im 8.659560562354934e-17 - 1.0im 1.0612750619050357 + 0.9045568943023813im 1.0000000000000002 + 1.0im 1.0612750619050357 - 0.9045568943023813im 1.0000000000000002 - 1.0im julia> acosh(0.0 + 0.0im) 0.0 + 1.5707963267948966im julia> acosh(0.0 - 0.0im) 0.0 - 1.5707963267948966im julia> acosh(-4.0 + 0.0im) 2.0634370688955608 + 3.141592653589793im julia> acosh(-4.0 - 0.0im) 2.0634370688955608 - 3.141592653589793im julia> for x = a b = atanh(x); println(b); println(tanh(b)) end 0.0 + 0.7853981633974483im 0.0 + 0.9999999999999999im 0.0 - 0.7853981633974483im 0.0 - 0.9999999999999999im 0.40235947810852507 + 1.0172219678978514im 1.0 + 1.0im 0.40235947810852507 - 1.0172219678978514im 1.0 - 1.0im julia> atanh(2.0 + 0.0im) 0.5493061443340549 + 1.5707963267948966im julia> atanh(2.0 - 0.0im) 0.5493061443340549 - 1.5707963267948966im julia> atanh(-4.0 + 0.0im) -0.2554128118829953 + 1.5707963267948966im julia> atanh(-4.0 - 0.0im) -0.2554128118829953 - 1.5707963267948966im