概要
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)`);
}
先に解説したように引数は数値でも複素数クラスでも受けられるようにしておきそれ以外が来たときは例外を飛ばすようにしておく