javascriptによる複素数のオブジェクトの作り方

 プログラム言語 javascript をマスターするうえで、越えなければならないハードルの一つにオブジェクトの考え方があります。C++やJavaなどのプログラム言語の経験がある方ならばともかく、いきなり「オブジェクト」と言われても理解に苦しみますよね。

 実は、オブジェクトをわかりやすく理解するための一つの “example” があります。それは複素数、ベクトルや行列などの数学的対象をオブジェクトの対象として扱うことです。

 例えば複素数の場合、複素数は実数部と虚数部のメンバから構成されていて絶対値を求めるとか、偏角を求めるという操作(メソッド)が存在します。このメンバとメソッドを一つにまとめる(カプセル化する)ことにより、複素数オブジェクトを作ります。さらに複素数の指数関数や三角関数などの複素関数は複素数から複素数への関数であるから、親オブジェクトである複素数オブジェクトから継承された複素関数オブジェクトをつくることができます。

 複素数オブジェクトと複素関数オブジェクトの作り方が、この記事の内容です。この記事を読むことで、カプセル化や継承などのオブジェクトの基本的概念に対する理解を深めることができると思います。

javascriptとは

 javascriptとは、WEBブラウザの上で動く手続き型の簡易プログラム言語で、クラス継承などの機能も取り込んでいるオブジェクト指向スクリプト言語です。

  • 制御構造( for, if など )による手続き型プログラム
  • オブジェクト( class など )によるオブジェクト指向プログラム

などを可能にするプログラム言語です。
 また、ボタンをクリックされた場合やチェックボックスを選択された場合などのイベント駆動型プログラミングにも向いています。

複素数のおはなし(簡単に)

最初に、複素数について簡単におさらいすれば

$ ( \sqrt{ – 1 } )^{ 2 } = – 1 $を満たす$ \sqrt{ – 1 } $を虚数単位といいます.$ a, b $を実数とするとき,実数の単位元$ 1 $と虚数単位との線形結合
$$ a + b \sqrt{ – 1 } $$
複素数( complex number )といいます.複素数どうしの四則演算を次の様に定義します.

  • $$ ( a + b \sqrt{ – 1 } ) + ( c + d \sqrt{ – 1 } ) = ( a + c ) + ( b + d ) \sqrt{ – 1 } $$
  • $$ ( a + b \sqrt{ – 1 } ) \ – \ ( c + d \sqrt{ – 1 } ) = ( a \ – \ c ) + ( b \ – \ d ) \sqrt{ – 1 } $$
  • $$ ( a + b \sqrt{ – 1 } ) \times ( c + d \sqrt{ – 1 } ) = ( a c \ – \ b d ) + ( b c + a d ) \sqrt{ – 1 } $$
  • $$ \frac{ a + b \sqrt{ – 1 } }{ c + d \sqrt{ – 1 } } = \frac{ ( a c + b d ) + ( b c \ – \ a d ) \sqrt{ – 1 } }{ c^{ 2 } + d^{ 2 } } $$

オブジェクトの作り方

 オブジェクトの話をする前に、C言語などで使われていた構造体について説明する必要があります。構造体は複数の変数をまとめて、一つの変数として扱う場合に使用します。例えば複素数の構造体を作る場合、実部と呼ぶ実数の変数と虚部と呼ぶ実数の変数とのペアを複素数の構造体として定義します。この構造体に、それぞれの変数に関連する関数を結び付けたものをオブジェクトと呼びます。

オブジェクトとは

 関連のあるデータと、そのデータを操作する機能との集合をオブジェクトと呼びます。たいていのオブジェクトは変数と関数で構成されていて、それぞれプロパティ( property )とメソッド( method )と呼ばれます。
 オブジェクトを使用するためには、定義したオブジェクトを実体(PC上のメモリと考えて良いと思います)にコピーします。この作業をインスタンス( instance )と言います。
 インスタンスは new 演算子により新しいオブジェクト名のオブジェクトを定義します。この時に、インスタンスと同時にオブジェクトのメンバを初期化したい場合は、コンストラクタ( construtor )メソッドを使います。

複素数のオブジェクト

 実部( real part )と呼ばれる実数値の変数と虚部( image part )と呼ばれる実数値の変数をメンバに持つ複素数のオブジェクトを作ります。実部( real )と虚部( image )を二つの引数に持つコンストラクタ・メソッドを定義します。このオブジェクトに作用するメソッドとして絶対値、加法、減法、乗法、商法を作ります。

メンバ
real複素数の実数部
image複素数の虚数部
メソッド戻り値
getComplex()複素数を取得するz:(complex)
setComplex( z )複素数を設定する
getReal()複素数の実数部を取得するReal
setReal( Real )複素数の実数部を設定する
getImage()複素数の虚数部を取得するImage
setImage( Image )複素数の虚数部を設定する
getAbs()複素数の絶対値を取得するabs
Add( w )複素数の足し算z = z + w
Sub( w )複素数の引き算z = z – w
Mult( w )複素数の掛け算z = z * w
Div( w )複素数の割り算z = z / w


/* 複素数( complex number )のオブジェクト ver. 1.00 2022/09/12 */

class complex {

    constructor(real, image) {

        this.real = real;
        this.image = image;
    }
    // 複素数を取得する
    getComplex() {

        var value = new complex(0.00, 0.00);
    
        value.setReal( this.real );
        value.setImage( this.image );

        return value;
    }
    // 複素数を設定する
    setComplex( real, image ) {

        this.real = real;
        this.image = image;
    }
    // 実部を取得する
    getReal() {

        return this.real;
    }
    // 実部を設定する
    setReal( real ) {

        this.real = real;
    }
    // 虚部を取得する
    getImage() {

        return this.image;
    }
    // 虚部を設定する
    setImage( image ) {

        this.image = image;
    }
    // 絶対値を取得する
    getAbs() {

        var abs = math.sqrt( this.real * this.real + this.image * this.image );

        return abs;
    }
    // 加法
    add( complex ) {

        this.real = this.real + complex.getReal();
        this.image = this.image + complex.getImage();
    }
    // 減法
    sub( complex ) {

        this.real = this.real - complex.getReal();
        this.image = this.image - complex.getImage();
    }
    // 乗法
    mult( complex ) {

        var real = this.real * complex.getReal() - this.image * complex.getImage();
        var image = this.real * complex.getImage() + this.image * complex.getReal();

        this.setComplex(real, image);
    }
    // 商法
    div( complex ) {

        var abs = complex.getAbs();

        if (this.abs != 0) {

            var real = this.real * complex.getReal() + this.image * complex.getImage();
            var image = this.image * complex.getReal() - this.real * complex.getImage();
    
            this.setComplex(real / abs, image / abs);
    
        }
    }
}

本プログラムの一部、または全部を使用することは自由ですが、そのことにより生じた事象に関して責任を負いかねません。また予告なく変更することがあります。予め、ご了承ください。

また、ご意見やご感想をお待ちしております。

複素数の三角関数

オイラーの公式から複素数の三角関数を定義する

 いま、$\theta \ $を実数とするとき
$$
\exp{ ( \sqrt{ -1 } \theta ) } = \cos \theta + \sqrt{ – 1 } \sin \theta
$$

が成り立つ。この恒等式がオイラーの公式( Euler`s formula )です。この公式により
$$
\exp{ ( – \sqrt{ – 1 } \theta ) }
= \exp{ ( \sqrt{ – 1 } ( – \theta ) ) }
= \cos ( – \theta ) + \sqrt{ – 1 } \sin ( – \theta )
= \cos \theta \ – \ \sqrt{ – 1 } \sin \theta
$$
となるから
$$
\cos \theta = \frac{ \exp{ ( \sqrt{ – 1 } \theta ) } + \exp{ ( – \sqrt{ – 1 } \theta ) } }{ 2 }
$$
$$
\sin \theta = \frac{ \exp{ ( \sqrt{ – 1 } \theta ) } \ – \ \exp{ ( – \sqrt{ – 1 } \theta ) } }{ 2 \sqrt{ – 1 } }
$$
が成り立つ。ここで実数$ \ \theta \ $を複素数$ \ z \ $で置き換えた式
$$
\cos z = \frac{ \exp{ ( \sqrt{ – 1 } z ) } + \exp{ ( – \sqrt{ – 1 } z ) } }{ 2 }
$$
$$
\sin z = \frac{ \exp{ ( \sqrt{ – 1 } z ) } \ – \ \exp{ ( – \sqrt{ – 1 } z ) } }{ 2 \sqrt{ – 1 } }
$$
を複素数の三角関数と定義します。
 最後に関数$ \ \exp{ ( \sqrt{ – 1 } z ) } $の実部と虚部を求めると、任意の$ \ z = x + \sqrt{ – 1 } y $に対して
$$
\begin{align*}
\exp{ ( \sqrt{ – 1 } z ) }
= \exp{ ( \sqrt{ – 1 } ( x + \sqrt{ – 1 } y ) ) }
& = \exp{ ( ( – y ) + \sqrt{ – 1 } x ) }
\\
& = \exp{ ( – y ) } \exp{ ( \sqrt{ – 1 } x ) }
\\
& = \exp{ ( – y ) } ( \cos{ x } + \sqrt{ – 1 } \sin{ x } )
\\
& = \exp{ ( – y ) } \cos{ x } + \sqrt{ – 1 } \exp{ ( – y ) } \sin{ x }
\end{align*}
$$
となります。

複素数の三角関数のオブジェクト

 複素数を引数とする複素関数のオブジェクトは、親オブジェクトである複素数オブジェクトから継承されたオブジェクトです。 extends キーワードにより、複素関数のオブジェクトを生成するための宣言をします。
 複素関数の計算後、親オブジェクトのメンバやメソッドを呼び出す場合は super キーワードを使用します。


/* 指数関数のクラス */
class expz extends complex {

    constructor(real, image) {

        var Re = Math.exp( real ) * Math.cos( image );
        var Im = Math.exp( real ) * Math.sin( image );

        super(Re, Im);
    }
}

class expiz extends complex {

    constructor(real, image) {

        var Re = Math.exp( - image ) * Math.cos( real );
        var Im = Math.exp( - image ) * Math.sin( real );

        super(Re, Im);
    }
}

/* 三角関数のクラス */
class cosz extends complex {

    constructor(real, image){

        var z1 = new expiz(real, image);                /* z1 = exp( iz )   */
        var z2 = new expiz(-real, -image);              /* z2 = exp( - iz ) */

        z1.add( z2 );                                   /* z1 = z1 + z2 = exp( iz ) + exp( - iz ) */

        super( z1.getReal() / 2, z1.getImage() / 2);    /* z1 = z1 / 2 */
    }
}

class sinz extends complex {

    constructor(real, image) {

        var z1 = new expiz(-real, -image);                /* z1 = exp( - iz ) */
        var z2 = new expiz(real, image);                  /* z2 = exp( iz )   */

        z1.sub( z2 );                                     /* z1 = z1 - z2 = exp( - iz ) - exp( iz ) */

        super( -(z1.getImage() / 2),  z1.getReal() / 2);  /* z1 = z1 / 2 */
    }
}

まとめ

 複素数オブジェクトを例に挙げ、javascript によるオブジェクトの作り方について説明しました。少しでも参考になれば、嬉しく思います。
 ここで載せたプログラム・リストの一部または全部をコピーして使用するのは自由ですが、その事に対する損害については責任を負えませんので、ご了承ください。


コメント