今回は複素数を表す Complex クラスを見ていきます。
クラス宣言
まずは Complex クラスのクラス宣言。 Complex は複素数体の元なので FieldElement インターフェースを実装しています。 ただし、複素数は順序を持たないため、Real クラスのように Comparable は実装していません:package org.apache.commons.math.complex; public class Complex implements FieldElement<Complex>, Serializable{ ... }
インスタンス生成
Complex クラスのインスタンスを取得するには主に以下の方法があります:- 実部、虚部から (コンストラクタによる生成)
- 極形式(絶対値と偏角)から (ComplexUtils#polar2Complex() メソッドによる生成)
- 文字列(実部、虚部)から (ComplexFormat クラスによる生成)
実部、虚部から
まずは実部と虚部を指定して Complex オブジェクトを取得する方法。 これは Complex クラスのコンストラクタを用います:public class Complex{ public Complex(double real, double imaginary){ ... } ... }
使い方は通常のコンストラクタの方法で:
def c = new Complex(1d, 2d) // 1 + 2i
極形式から
次は極形式、つまり絶対値と偏角から Complex オブジェクトを取得する方法。 これには ComplexUtils クラスの static メソッド polar2Complex() を使います。public class ComplexUtils{ public static Complex polar2Complex(double r, double theta){...} }
第1引数は生成する複素数の絶対値なので非負でなければなりません(負の数を指定すると例外が投げられます)。 また、第2引数は偏角ですが、これは弧度法(ラジアン)で指定する必要があります。 極形式についての簡単な説明はこの記事の最後で。 使い方はこんな感じ:
def c = new Complex(1d, Math.sqrt(3d)) // 1 + √3 i // 実際には double の精度ではアサーションは通りませんが・・・ assert ComplexUtils.polar2Complex(2d, Math.PI/3d) == c // 2exp(i π/3) = 2(cos(π/3) + i sin(π/3))
文字列(実部、虚部)から
インスタンス生成の最後は文字列からの変換。 これには ComplexFormat クラスを使います:def format1 = new ComplexFormat() // def format1 = ComplexFormat.getInstance() でも可。 assert format1.parse('1 + 2i') == new Complex(1d, 2d) def format2 = new ComplexFormat('j') assert format2.parse('1 + 2j') == new Complex(1d, 2d)
虚数単位の文字指定(デフォルトは "i")は ComplexFormat クラスのコンストラクタで指定できます。
メソッド
次はメソッドの挙動。 いくつかのグループに分類してますが、特に厳密な区分けがあるわけではありません。- 値評価
- プロパティ取得など
- 四則演算
- (複素関数)
値評価
まずは値の評価に関するメソッド。 概ね boolean 値を返すメソッドを集めてます:public class Complex{ ... boolean equals(Object other) int hashCode() boolean isInfinite() boolean isNaN() }
equals() メソッドは通常の値オブジェクトとしての挙動に合うように、実部、虚部の値の等値評価を行います。 isInfinite(), isNaN() メソッドの挙動は以下のサンプルを参照:
// Infinity どれも Complex.INF に等しい assert new Complex(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY).isInfinite() assert new Complex(Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY).isInfinite() assert new Complex(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY).isInfinite() assert new Complex(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY).isInfinite() assert new Complex(Double.POSITIVE_INFINITY, 1d).isInfinite() assert new Complex(Double.NEGATIVE_INFINITY, 1d).isInfinite() assert new Complex(1d, Double.POSITIVE_INFINITY).isInfinite() assert new Complex(1d, Double.NEGATIVE_INFINITY).isInfinite() // NaN どれも Complex.NaN に等しい assert new Complex(Double.NaN, Double.NaN).isNaN() assert new Complex(Double.NaN, 1d).isNaN() assert new Complex(1d, Double.NaN).isNaN()
プロパティ取得など
次は数値を返すメソッド。- getReal(), getImaginary(), abs(), getArgument() ・・・ double 値を返す
- negate(), conjugate() ・・・ Complex オブジェクトを返す
public class Complex{ ... // 複素数体 ComplexField のインスタンスを取得 ComplexField getField() // この Complex オブジェクトが表している複素数を z = x + yi とすると double getReal() // 実部 x を返す double getImaginary() // 虚部 y を返す double abs() // 絶対値 |z| = √(x^2 + y^2) を返す double getArgument() // 偏角 arg(z) = arctan(y / x) を返す Complex negate() // -x - yi を返す Complex conjugate() // 複素共役 x - yi を返す }
各メソッドの返り値の詳細(数学)はこの記事の最後参照。 また、getArgument() メソッドで返される偏角 の値の範囲は
です。 詳しくは java.lang.Math#atan2(double, double) メソッドの JavaDoc 参照。 各メソッドのサンプルはこんな感じ:
def c0 = new Complex(1d, 3d) // = 1 + 3i assert c0.getReal() == 1d // = 1 assert c0.getImaginary() == 3d // = 3 assert c0.abs() == Math.hypot(1d, 3d) // = √(1^2 + 3^2) assert c0.getArgument() == Math.atan(3d / 1d) // = arctan(3) assert c0.negate() == new Complex(-1d, -3d) // = - 1 - 3i assert c0.conjugate() == new Complex(1d, -3d) // = 1 - 3i
四則演算
次は複素数の四則演算。 大半は FieldElement インターフェス(→)に定義されているメソッドのオーバーライドです。 multiply() メソッド(乗法)は double 値をとるものも定義されていますが。public class Complex{ ... Complex add(Complex rhs) Complex subtract(Complex rhs) Complex multiply(Complex rhs) Complex multiply(double rhs) Complex divide(Complex rhs) }
使用方法は特に難しいことはないと思います:
def c0 = new Complex(1d, 3d) def c1 = new Complex(3d, 4d) assert c0.add(c1) == new Complex(4d, 7d) assert c0.subtract(c1) == new Complex(-2d, -1d) assert c0.multiply(c1) == new Complex(-9d, 13d) assert c0.divide(c1) == new Complex(0.6d, 0.2d)
定義済み定数
Complex クラスに static フィールドとして定義されている複素数には以下のものがあります:定数名 | 値 |
---|---|
ZERO | 0.0 + 0.0i (= 0 ) |
ONE | 1.0 + 0.0i (= 1) |
I | 0.0 + 1.0i (= i ) |
INF | +INF + INFi |
NaN | NaN + NaNi |
ZERO と ONE は(Field インターフェースの実装クラスである) ComplexField クラスから getZero(), getOne() メソッドによって取得できます。
ちょっと数学を
複素数の演算等を数式で書いておきましょう。 以下、
とします。
極形式
複素数 の絶対値 と偏角 は以下のように表されます:
これを逆に解くと
となります。 ちなみに、極形式はオイラーの公式を使うと簡単に書き下せます:
四則演算
2つの複素数の四則演算は以下のように計算できます( は実数)
複素共役
複素数 z の複素共役 (complex conjugate) (もしくは )は
で与えられます。 ある複素数とその共役な複素数との間の和と積は
となり、どちらも実数になります。
数学ガール フェルマーの最終定理 (数学ガールシリーズ 2)
- 作者: 結城浩
- 出版社/メーカー: ソフトバンククリエイティブ
- 発売日: 2008/07/30
- メディア: ペーパーバック
- 購入: 35人 クリック: 441回
- この商品を含むブログ (260件) を見る
- 作者: 奥村晴彦,杉浦方紀,津留和生,首藤一幸,土村展之
- 出版社/メーカー: 技術評論社
- 発売日: 2003/05
- メディア: 単行本
- 購入: 2人 クリック: 61回
- この商品を含むブログ (61件) を見る