倭算数理研究所

科学・数学・学習関連の記事を、「倭マン日記」とは別に書いていくのだ!

commons-math 解読 (2) : MathUtils に定義されている static メソッド〜指数・対数関数編〜

今回は MathUtils に定義されている static メソッドのうち、指数・対数関数、双曲線関数を見ていきます。 今回見ていくメソッドは下表の通り:

メソッド 返り値の型 説明
pow(int k, int e)
pow(int k, long e)
pow(long k, int e)
pow(long k, long e)
pow(BigInteger k, int e)
pow(BigInteger k, long e)
pow(BigInteger k, BigInteger e)
int
int
long
long
BigInteger
BigInteger
BigInteger
冪乗
scalb(double d, int scaleFactor) double d×2scaleFactor
log(double base, double x) double 対数関数
sinh(double x)
cosh(double x)
double 双曲線関数

冪乗 (Power) { a^x }

まずは冪乗 (power)。 java.lang.Math にも pow() メソッドは定義されていますが、2つの引数がどちらも double となっています:

package java.lang;

public final class Math{
    ...
    public static double pow(double a, double x){ ... }
}

MathUtils では、その他のプリミティブ型(整数)や java.math.BigInteger に対してこのメソッドオーバーロードしてる感じです(整数関数に分類した方がよかったかな?)。 使い方は同じ:

assert MathUtils.pow(2, 10) == 2**10    // 1024

Scalb

これは java.lang.Math にも定義されています(1.6 以降)。 scalb(d, scaleFactor) は d×2scaleFactor を返します。

import static java.lang.Math.scalb

assert MathUtils.scalb(3d, 10) == scalb(3d, 10)    // 3*2**10 = 3072

対数関数 (Logarithm) { \log_a b }

対数関数 (logarithm) は java.lang.Math にも定義されていますが、底として扱えるのが自然対数の底(Math.log() の場合)もしくは 10 (Math.log10() の場合)と決まっていました:

package java.lang;

public final class Math{
    ...
    public static double log(double x){ ... }
    public static double log10(double x){ ... }
    public static double log1p(double x){ ... }    // log(1+x) と同じ
}

MathUtils では任意の値を底にすることができます(ただし、数学で許される範囲*1)。

import static java.lang.Math.E
import static java.lang.Math.log
import static java.lang.Math.log10

assert MathUtils.log(E, 3d) == log(3d)    // 1.0986122886681098
assert MathUtils.log(10d, 3d) == log10(3d)    // 0.47712125471966244
assert MathUtils.log(2d, 3d) == log(3d) / log(2d)    // 1.5849625007211563 底が2、真数が3の対数

最後の行では、底の変換公式

  { \displaystyle
\begin{align*}
    \log_a b = \frac{\log b}{\log a}
\end{align*}
}

を使っています。

双曲線関数 (Hyperbolic Function) { \sinh,\, \cosh }

最後は双曲線関数 (hyperbolic function)。 これらは java.lang.Math にも定義されています(1.5 以降。 tanh() メソッドも定義されてます)。 双曲線関数は指数関数を使ってこんな感じに定義されてました:

  { \displaystyle
\begin{align*}
    \sinh \theta &= \frac{e^\theta - e^{-\theta}}{2}, & \cosh \theta &= \frac{e^\theta + e^{-\theta}}{2}
\end{align*}
}

{ x = \cosh\theta,\,y = \sinh\theta } とおくと

  { \displaystyle
\begin{align*}
    x^2 - y^2 = 1
\end{align*}
}

が成り立つので双曲線関数と呼ぶんでしたね。

import static java.lang.Math.sinh
import static java.lang.Math.cosh

assert MathUtils.sinh(2d) == sinh(2d)    // 3.626860407847019
assert MathUtils.cosh(2d) == cosh(2d)    // 3.7621956910836314

余談
三角関数は指数関数を使って

  { \displaystyle
\begin{align*}
    \sin \theta &= \frac{e^{i\theta} - e^{-i\theta}}{2i}, &
    \cos \theta &= \frac{e^{i\theta} + e^{-i\theta}}{2} &
    (i = \sqrt{-1})
\end{align*}
}

と定義され、{ x = \cos\theta,\,y = \sin\theta } とおくと

  { \displaystyle
\begin{align*}
    x^2 + y^2 = 1
\end{align*}
}

が成り立ちます。 また { \sin\theta,\,\cos\theta } の定義式からオイラーの公式

  { \displaystyle
\begin{align*}
    e^{i\theta} = \cos\theta + i \sin\theta
\end{align*}
}

が成り立つことが分かります(オイラーの公式から上の関係式が出てくるのかな?)。

Javaによるアルゴリズム事典

Javaによるアルゴリズム事典

*1:数学では { a > 0, a != 1, b > 0 } という条件が課されます。 ただし、このメソッドは a や b が 0 でも 0 や NaN が返されるようです。