今回は複素数を表す Complex クラスにメソッドを追加していきます。
インスタンス生成
まずはやっぱりインスタンス生成。 Complex クラスにも、分数 Fraction クラスに追加したようなメソッドを定義してますが、なんと言っても以下のようにインスタンス化できるのがエレガント!@GrabResolver('http://www5.ocn.ne.jp/~coast/repo/') @Grab('org.waman.math:wamans-math:0.0.1') // static import しておこう! import static org.apache.commons.math.complex.Complex.I WamansMath.enhance(CommonsMathPackage.COMPLEX) // まるで言語レベルで複素数をサポートしてるようなインスタンス化!! assert 1 + 2*I == new Complex(1d, 2d)
static import 文によって Complex.I を読み込む必要がありますが、それを行えば「1 + 2*I」という式で Complex オブジェクトが生成できます! ほとんど言語レベルで複素数をサポートしてるのと変わりませんね。
他にも(Number の)配列や String / GString から Complex オブジェクトを生成するメソッドも追加してます:
@GrabResolver('http://www5.ocn.ne.jp/~coast/repo/') @Grab('org.waman.math:wamans-math:0.0.1') import static org.apache.commons.math.complex.Complex.I WamansMath.enhance(CommonsMathPackage.COMPLEX) // Number の配列からインスタンス化 assert [1, 2].complex() == 1 + 2*I // String, GString からインスタンス化 assert '3 + 4i'.complex() == 3 + 4*I assert '5 + 6j'.complex('j') == 5 + 6*I assert "7 + 8i".complex() == 7 + 8*I // Complex に追加した parse() メソッドによって String からインスタンス化 assert Complex.parse('1 + 2i') == 1 + 2*I assert Complex.parse('1 + 2j', 'j') == 1 + 2*I
虚数単位をお好みに合わせて 'j' にすることもできます。
メソッド使用サンプル
次はメソッドの使用方法。 これらは Fraction クラスに追加したメソッドと大体同じです。 少々変えてるのは ~ (bitwiseNegate) が複素共役を返すことくらいです。- 単項演算
- Complex 同士の演算
- Complex と Number の演算
単項演算
@GrabResolver('http://www5.ocn.ne.jp/~coast/repo/') @Grab('org.waman.math:wamans-math:0.0.1') import static org.apache.commons.math.complex.Complex.I WamansMath.enhance(CommonsMathPackage.COMPLEX) def c = 1 + 3*I // 符号 assert +c == 1 + 3*I assert -c == -1 - 3*I // 共役な複素数 assert ~c == 1 - 3*I // 絶対値 返り値の型は double assert c.abs() == sqrt(10) // √1^2 + 3^2
Complex 同士の演算
@GrabResolver('http://www5.ocn.ne.jp/~coast/repo/') @Grab('org.waman.math:wamans-math:0.0.1') import static org.apache.commons.math.complex.Complex.I WamansMath.enhance(CommonsMathPackage.COMPLEX) def c0 = 1 + 3*I def c1 = 3 + 4*I assert c0 + c1 == 4 + 7*I assert c0 - c1 == -2 - I assert c0 * c1 == -9 + 13*I assert c0 / c1 == 0.6d+ 0.2d*I
Complex と Number の演算
@GrabResolver('http://www5.ocn.ne.jp/~coast/repo/') @Grab('org.waman.math:wamans-math:0.0.1') import static org.apache.commons.math.complex.Complex.I WamansMath.enhance(CommonsMathPackage.COMPLEX) def c = 1 + 3*I assert c + 1 == 2 + 3*I assert c - 2 == -1 + 3*I assert c * 3 == 3 + 9*I assert c / 10 == 0.1d + 0.3d*I assert 1 + c == 2 + 3*I assert 2 - c == 1 - 3*I assert 3 * c == 3 + 9*I assert 4d / c == 0.4d - 1.2d*I
Groovy の力を借りるとかなり簡潔にコードが書けまする!
メソッド追加の詳細
一応、メソッド追加の詳細も載せておきます。 そのうち変更されてるかも知れないけど。// -1 を追加 def _1 = new Complex(-1d, 0d) ComplexField.metaClass.getMinusOne = { -> _1 } Complex.metaClass.'static'.getMINUS_ONE = { -> _1 } // -i を追加 def _I = new Complex(0d, -1d) ComplexField.metaClass.getMinusI = { -> _I } Complex.metaClass.'static'.getMINUS_I = { -> _I } // Complex にメソッドを追加 Complex.metaClass.define{ // 単項演算 isMinusOne = { -> delegate == _1 } negative = { -> negate() } bitwiseNegate = { -> conjugate() } // Complex 同士の演算 plus = { Complex c -> add(c) } minus = { Complex c -> subtract(c) } div = { Complex c -> divide(c) } power = { Complex c -> pow(c) } // Number との演算 plus = { Number arg -> add(arg.complex()) } minus = { Number arg -> subtract(arg.complex()) } multiply = { Number arg -> multiply(arg.complex()) } div = { Number arg -> divide(arg.complex()) } power = { Number arg -> pow(arg.complex()) } // 型変換 asType = { Class type -> switch(type){ case Complex: return delegate case String: return ComplexFormat.instance.format(delegate) case List: return [getReal(), getImaginary()] case double[]: return [getReal(), getImaginary()] as double[] default: assert false } } } // Complex#parse() メソッド Complex.metaClass.'static'.parse = { String arg, String i = null -> (i == null) ? ComplexFormat.instance.parse(arg) : new ComplexFormat(i).parse(arg) } // Complex 以外に追加するメソッド Number.metaClass.define{ complex = { new Complex(doubleValue(), 0d) } plus = { Complex c -> complex().add(c) } minus = { Complex c -> complex().subtract(c) } multiply = { Complex c -> complex().multiply(c) } div = { Complex c -> complex().divide(c) } power = { Complex c -> complex().pow(c) } } List.metaClass.complex = { -> new Complex(*delegate) } String.metaClass.complex = { String i = null -> Complex.parse(delegate, i) } }
- 作者: 奥村晴彦,杉浦方紀,津留和生,首藤一幸,土村展之
- 出版社/メーカー: 技術評論社
- 発売日: 2003/05
- メディア: 単行本
- 購入: 2人 クリック: 61回
- この商品を含むブログ (61件) を見る