倭算数理研究所

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

倭マン's Math (2) : ContinuedFraction (org.apache.commons.math.util パッケージ)

今回は連分数を実装する ContinuedFraction クラス(一覧)。

ContinuedFraction クラスを使用する場合は、サブクラスもしくは無名クラスによって抽象メソッド getA(), getB() の実装を行う必要がありました(こちら参照)。 Java ではそれで仕方ありませんでしたが、Groovy では処理をオブジェクトとして扱えるクロージャがサポートされているので、これらから ContinuedFraction オブジェクトを生成できるようにしてみます。

ClosureContinuedFraction クラス


まずは Groovy のクロージャ (groovy.lang.Closure) を連分数の評価に使う、ContinuedFraction のサブクラスを定義します:

import groovy.lang.Closure;
import org.apache.commons.math.util.ContinuedFraction;

class ClosureContinuedFraction extends ContinuedFraction{

    private Closure a, b;

    public ClosureContinuedFraction(){}

    public ClosureContinuedFraction(Closure a, Closure b){
        this();
        this.a = a;
        this.b = b;
    }

    public Closure getA() { return a; 
    public void setA(Closure a) { this.a = a; }

    public Closure getB() { return b; }
    public void setB(Closure b) { this.b = b; }

    @Override
    protected double getA(int i, double v) {
        return (Double)this.a.call(new Object[]{i, v});
    }

    @Override
    protected double getB(int i, double v) {
        return (Double)this.b.call(new Object[]{i, v});
    }
}

これは Java クラスとして実装しています。

拡張


上記の ClosureContinuedFraction クラスを踏まえて、2つのクロージャから ContinuedFraction オブジェクトを生成する create() メソッドを ContinuedFraction クラスの static メソッドとして定義しましょう:

        ContinuedFraction.metaClass.'static'.create = { Closure a, Closure b ->
            return new ClosureContinuedFraction(a, b)
        }

まぁ、何てことないですね。

使用方法


追加した create() メソッドは以下のようにして使います:

@GrabResolver('http://www5.ocn.ne.jp/~coast/repo/')
@Grab('org.waman.math:wamans-math:0.0.1')

WamansMath.enhance(CommonsMathPackage.UTIL)

def a = { int n, double x -> (n == 0) ? 3d : 6d }
def b = { int n, double x -> double y = (2d * n) - 1d; y*y }

def frac = ContinuedFraction.create(a, b)
frac.evaluate(0d, 0.0000001d)

パフォーマンスは Pure Java に比べて10分の1くらいになってしまいますが・・・

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

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