スポンサード リンク

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

スポンサード リンク
-- : -- : -- | スポンサー広告 | page top↑
スポンサード リンク

不変クラスとして設計した複素数クラスComplex(Javaによる実装)

Javaで複素数(complex number)クラスComplexを作ってみました。

メソッド

  • Complex(double re, double im) /* 引数に実部(real part)と虚部(imaginary part)の値を取るコンストラクタです。 */
  • re(): double /* 実部の値を返すアクセサ(accessor)です。 */
  • im(): double /* 虚部の値を返すアクセサです。 */
  • add(Complex c): Complex /* 引数に取った複素数との和を計算して、その値を保持するインスタンスを返します。 */
  • sub(Complex c): Complex /* 引数に取った複素数との差を計算して、その結果を保持するインスタンスを返します。 */
  • mul(Complex c): Complex /* 引数に取った複素数との積を計算して、その結果を保持するインスタンスを返します。 */
  • div(Complex c): Complex /* 引数に取った複素数との商を計算して、その結果を保持するインスタンスを返します。 */
  • Con(Complex c): Complex /* 引数に取った複素数の複素共役(complex conjugate)を計算して、その結果を保持するインスタンスを返します。 */
  • abs(): double /* 絶対値(absolute value)を計算して、その値を返します。 */
  • arg(): double /* 偏角(argument)を計算して、その値を返します。 */
  • toString(): String /* 複素数を表す文字列を(a+bi)の形式で返します。 */

プログラム: Complex.java

public class Complex {
    private final double re;
    private final double im;
    
    public Complex(double re, double im) {
        this.re = re;
        this.im = im;
    }
    
    public double re() { return re; }
    public double im() { return im; }
    
    public Complex add(Complex c) {
        return new Complex(re + c.re, im + c.im());
    }
    
    public Complex sub(Complex c) {
        return new Complex(re - c.re, im - c.im);
    }
    
    public Complex mul(Complex c) {
        return new Complex(
            re*c.re - im*c.im, re*c.im + im*c.re);
    }
    
    public Complex div(Complex c) {
        double denominator = c.re*c.re + c.im*c.im;
        return new Complex(
            (re*c.re + im*c.im)/denominator,
            (im*c.re - re*c.im)/denominator);
    }
    
    public Complex Con() {
        return new Complex(re, -im);
    }

    public double abs() {
        return Math.sqrt(re*re + im*im);
    }
    
    public double arg() {
        return Math.atan(im/re);
    }
    
    public String toString() {
        if(im >= 0) 
            return "(" + re + " + " + im + "i" + ")";
        else
            return "(" + re + " - " + -im + "i" + ")";
    }

}

解説

Effective Javaで推奨されている不変クラス(immutable class)として設計したため、addなどのメソッドではオブジェクトの値を書き換えるのではなく、新しいオブジェクトを生成して返しています。フィールドreとimがfinalなのもこのためです。

div()において、あらかじめ分母(c.re*c.re + c.im*c.im)を計算して一時変数denominatorに格納しているのは、この計算を2度行うとパフォーマンスが低下するためです。このように、複数回オブジェクトを参照する場合はその値を一時変数に格納することでパフォーマンスが向上します。

Effective Java プログラミング言語ガイドEffective Java プログラミング言語ガイド
Joshua Bloch

ピアソン・エデュケーション 2001-12-03
売り上げランキング : 9976
おすすめ平均

Amazonで詳しく見る
by G-Tools

テスト用のmainメソッド

    public static void main(String args[]) {
        Complex c1 = new Complex(1, 2);
        Complex c2 = new Complex(3, 4);
        
        System.out.println(
            c1 + " + " + c2 + " = " + c1.add(c2));
        System.out.println(
            c1 + " - " + c2 + " = " + c1.sub(c2));
        System.out.println(
            c1 + " * " + c2 + " = " + c1.mul(c2));
        System.out.println(
            c1 + " / " + c2 + " = " + c1.div(c2));
        
        System.out.println(
            "Con " + c1 + " = " + c1.Con());
        System.out.println(
            "|" + c1 + "|" + " = " + c1.abs());
        System.out.println(
            "arg" + c1 + " = " + c1.arg());
    }

実行結果

(1.0 + 2.0i) + (3.0 + 4.0i) = (4.0 + 6.0i)
(1.0 + 2.0i) - (3.0 + 4.0i) = (-2.0 - 1.0i)
(1.0 + 2.0i) * (3.0 + 4.0i) = (-5.0 + 10.0i)
(1.0 + 2.0i) / (3.0 + 4.0i) = (0.44 + 0.08i)
Con(1.0 + 2.0i) = (1.0 - 2.0i)
|(1.0 + 2.0i)| = 2.23606797749979
arg(1.0 + 2.0i) = 1.1071487177940904

スポンサード リンク

テーマ:プログラミング - ジャンル:コンピュータ - ソーシャルブックマーク: この記事をクリップ! Yahoo!ブックマークに登録

22 : 10 : 19 | プログラミング-Java | トラックバック(0) | コメント(6) | page top↑
<<演算子のオーバーロードを使用した複素数クラスComplex(C#による実装) | ホーム | 正確な値が要求される計算にfloat,double型は使えない!>>
コメント

Complexクラスを引数にとるメソッドのc.reとc.imは、privateフィールドなのにアクセスできるんだ!?同じクラスだからかな?本来ならc.re()とc.im()にすると思ってた!
by: うえちょこ * 2008/08/14 20:31 * URL [ 編集] | page top↑

>うえちょこ

俺も最初はc.re()とc.im()で書いてたけど、間違いがないかEffective Javaのプログラムと見比べたらEffective Javaではc.reとc.imになっててびっくりした。

Effective Javaの間違いかとも思ったんだけど、何度も印刷されている本だからこの程度の間違いなんてとっくに直ってるだろうし、Eclipseでも c. まで打つと候補にc.reもc.re()も両方出てくるから「もしかして…?」って思って試してみたら問題なく動いた。

違うオブジェクトでも、クラスが同じならprivateのフィールドもアクセスできるみたいだね。これはすごく勉強になった。
by: TBVector * 2008/08/14 23:21 * URL [ 編集] | page top↑
本当ですか?
>div()において、あらかじめ分母(c.re*c.re + c.im*c.im)を計算して一時変数denominatorに格納しているのは、この計算を2度行うとパフォーマンスが低下するためです。このように、複数回オブジェクトを参照する場合はその値を一時変数に格納することでパフォーマンスが向上します。

これですが、これは本当ですか?
最適化処理の段階でまとめられたりはしないんですか?パフォーマンスが向上しますというのであればちゃんと実験して検証すべきだと思います。
by: akiraviz * 2008/12/21 19:07 * URL [ 編集] | page top↑

>akiravizさん
本当です。

実際に検証してみました。
http://networkprogramming.blog18.fc2.com/blog-entry-113.html
by: TBVector * 2008/12/22 00:58 * URL [ 編集] | page top↑

引き算の"return new Complex(re - c.re, im - c.re);"が間違っているようです.
by: * 2009/03/22 09:14 * URL [ 編集] | page top↑

>引き算の"return new Complex(re - c.re, im - c.re);"が間違っているようです.

ご指摘ありがとうございます。

return new Complex(re - c.re, im - c.im);

に修正しました。
by: TBVector * 2009/03/22 10:36 * URL [ 編集] | page top↑

コメントの投稿














管理者にだけ表示を許可する

トラックバック
トラックバックURL
http://networkprogramming.blog18.fc2.com/tb.php/78-534e275d
この記事にトラックバックする(FC2ブログユーザー)
| ホーム |

プロフィール

Author:TBVector

プロフィール

メールフォーム

記事検索

Google

最近の記事

人気の記事

過去の記事

カテゴリー

タグランキング

リンク

最近のコメント

最近のトラックバック

アクセスカウンタ

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。