以前から気になっていた「commons-math」の API を気ままにいじっていきます。 当面は、簡単に使える org.apache.commons.math.util.MathUtils に定義されている static メソッドをあれこれ。
正直、commons-math を使うコードを Java で書くのは億劫なので、サンプルコードは Groovy で書いていきます(パフォーマンスなんてクソ喰らえ!)。 ホントは Scala の方がいい気もしますが、まだ勉強中なので断念。
で、この記事中のサンプルコードには、最初に
@Grab(group='org.apache.commons', module='commons-math', version='2.1') import org.apache.commons.math.util.MathUtils
の2行がついていると思ってください。 また、Grape の設定もされてる前提で。 もちろん、別途 commons-math の Jar ファイルをとってきて CLASSPATH 上に配置しても構いませんが。
また、『Groovyイン・アクション』みたく assert を多用していますが、見やすさのために double (Double) 値も普通に等値評価してます。 くれぐれも良い子はマネしないでください*1。
MathUtils クラス
MathUtils は java.lang.Math のようなユーティリティ・クラスで、たくさんの数学関数が static メソッドとして定義されています。 java.lang.Math のメソッドを拡張したものもあれば、java.lang.Math に追加されたためダブっているものもあります。 1つの記事に全部のメソッドを書くのは大変なので、独断と偏見にて以下のように分類します:結構適当に分類して名前つけてます。 あまり細かいところは気にしないでね。 今回は整数関数。
整数関数
今回は下表に載っている関数を見ていきます:メソッド | 返り値の型 | 説明 |
---|---|---|
factorial(int n) factorialDouble(int n) factorialLog(int n) |
long double double |
階乗 |
binomialCoefficient(int n, int k) binomialCoefficientDouble(int n, int k) binomialCoefficientLog(int n, int k) |
long double double |
二項係数 |
gcd(int p, int q) gcd(long p, long q) |
int long |
最大公約数 (GCD : Greatest Common Divisor) |
lcm(int a, int b) lcm(long a, long b) |
int long |
最小公倍数 (LCM : Least Common Multiple) |
整数関数というより自然数関数ですが何か?
階乗 (Factorial)
まずは階乗 (factorial)。 数学っぽく書くとこんな定義:が大きくなると は急激に大きくなるので、返り値は long (factorial() の場合)もしくは double (factorialDouble() の場合)になっています。 加えて、それらの対数値を返すメソッドも定義されています。 サンプルコードはこんな感じ:
import static java.lang.Math.log assert MathUtils.factorial(10) == 10*9*8*7*6*5*4*3*2*1 // 3628800 assert MathUtils.factorialDouble(10) == 10*9*8*7*6*5*4*3*2*1 // 3628800.0d assert MathUtils.factorialLog(10) == log(10*9*8*7*6*5*4*3*2*1) // 15.104412573075516d
factorialDouble() メソッドは Double Factorial (n!!) ではないので注意。
二項係数 (Binomial Coefficient)
次は二項係数 (binomial coefficient)。 数学的な表記はいくつかあります:メソッドのポストフィックス 'Double', 'Log' は factorial の場合と同じ:
import static java.lang.Math.log assert MathUtils.binomialCoefficient(10, 3) == (10*9*8).intdiv(3*2*1) // 120 assert MathUtils.binomialCoefficientDouble(10, 3) == (10*9*8)/(3*2*1) // 120.0d assert MathUtils.binomialCoefficientLog(10, 3) == log((10*9*8)/(3*2*1)) // 4.787491742782046d
Groovy では整数の割り算は intdiv() メソッドを使うんでした。
最大公約数 (GCD) ・最小公倍数 (LCM)
最後は最大公約数 (GCD : Greatest Common Devisor) と最小公倍数 (LCM : Least Common Multiple)。 えーと、定義はいいかな。assert MathUtils.gcd(210, 196) == 14 assert MathUtils.gcd(2*3*5*7, 2*2*7*7) == 2*7 // 2*3*5*7 = 210, 2*2*7*7 = 196 assert MathUtils.lcm(210, 196) == 2940 assert MathUtils.lcm(2*3*5*7, 2*2*7*7) == 2*2*3*5*7*7 // 2*2*3*5*7*7 = 2940
各行のメソッドの引数に使っている数字は同じです。 書き方を変えてみましたが意味は分かるかな?
- 作者: 奥村晴彦,杉浦方紀,津留和生,首藤一幸,土村展之
- 出版社/メーカー: 技術評論社
- 発売日: 2003/05
- メディア: 単行本
- 購入: 2人 クリック: 61回
- この商品を含むブログ (61件) を見る