LoginSignup
2
0

JavaScriptで複素数クラスを作る

Posted at

概要

JavaScriptで数値計算するたに前にJavaScriptが実行できるテストページを作った。
そのテストページには四則演算子をBabelを使ってJavaScriptでなんちゃって演算子オーバーロード化してある](https://qiita.com/I-Yasusi/items/ad0f174e8d5f14d598b9)。
その演算子オーバーロードを使ったクラスの例として作った複素数クラスについて解説する。
作ったものはGithubのhttps://github.com/T-Yasusi/t-yasusi.github.io/blob/main/js/modules/calc/class/Complex.jsにおいてあります。

TypeScriptによる擬似メソッド列挙

Complex{
   constructor(real :number, imag :number);
   
   re() : number // 実部の別名
   im() : number // 虚部の別名
   abs2() : number // 絶対値の二乗
   abs() : number // 絶対値
   arg() : number // 偏角
   minus() : Complex // -z
   reverse(): Complex // 逆数
   conj() : Complex // 複素共役

   add(a : number | Complex) : Complex // 足し算
   sub(a : number | Complex) : Complex // 引き算
   mul(a : number | Complex) : Complex // 掛け算
   div(a : number | Complex) : Complex // 割り算

   toString() : string 
   toTex() : string // MathJax用
   toEffNum(n : number) : string // 浮動点少数以下の定義付き 
}

四則演算は数字でも複素数でも受けられるように内部では実装する。

実際のソースコード

コンストラクタとユーティリティメソッド

toString toTex toEffNumは割愛する。

Complex.js
class Complex{
    constructor(a, b){
        this.real=a;
        this.imag=b;
    }

    set re(a){ this.real=a; }
    get re(){ return this.real; }
    set im(a){ this.imag=a; }
    get im(){ return this.imag; }

    abs2(){ return this.real*this.real+this.imag*this.imag; }
    abs(){ return Math.sqrt(this.real*this.real+this.imag*this.imag); }
    arg(){ return Math.atan2(this.imag, this.real); }
    minus(){ return new Complex(-this.real, -this.imag); }
    reverse(){
        const r2=this.abs2();
        return new Complex(this.real/r2, -this.imag/r2);
    }
    conj(){ return new Complex(this.real, -this.imag); }

絶対値は内部でMath.sqrtを呼んでいるのでabs2のほうが高速(気になるほどではないが)

四則演算子

Complex.js
    add(a){
        if( typeof(a)==='number' ) return new Complex(this.real+a, this.imag);
        if( (a instanceof Complex)===true ) return new Complex(this.real+a.real, this.imag+a.imag);

        throw new Error(`!!! Complex.add error !!! args=typeof(a)`+typeof(a));
    }
    sub(a){
        if( typeof(a)==='number' ) return new Complex(this.real-a, this.imag);
        if( (a instanceof Complex)===true ) return new Complex(this.real-a.real, this.imag-a.imag);

        throw new Error(`!!! Complex.sub error !!! args=typeof(a)`);
    }
    mul(a){
        if( typeof(a)==='number' ) return new Complex(a*this.real, a*this.imag);
        if( (a instanceof Complex)===true ) return new Complex(this.real*a.real-this.imag*a.imag, this.real*a.imag+this.imag*a.real);

        throw new Error(`!!! Complex.mul error !!! args=typeof(a)`);
    }
    div(a){
        if( typeof(a)==='number' ) return new Complex(this.real/a, this.imag/a);
        if( (a instanceof Complex)===true ) return this.mul(a.reverse());

        throw new Error(`!!! Complex.div error !!! args=typeof(a)`);
    }

先に解説したように引数は数値でも複素数クラスでも受けられるようにしておきそれ以外が来たときは例外を飛ばすようにしておく

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0