3.2 + 4i 1 + 3i 1 + 2.3i
上の例のように、複素数には実部と虚部があります。
通常は、0+3i のように完全に虚部だけのものは通常 3i と書き、5+0i のように完全に実部だけのものは通常 5 と書きます。しかし、データ型 complex を使用すると複素数を表現することができます。
複素数ライブラリ (libcomplex) は、-compat=4 でのみ使用できます (廃止されていません)。-compat=5 では、C++ 標準ライブラリ (libcstd) に組み込まれています。
複素数ライブラリは、新しいデータ型として複素数データ型を実装します。このライブラリには以下が含まれています。
演算子
数学関数 (組み込み数値型用に定義されている関数)
拡張機能 (複素数の入出力を可能にする iostream 用)
エラー処理機能
複素数には、実部と虚部による表現方法の他に、絶対値と偏角による表現方法があります。複素数ライブラリには、実部と虚部によるデカルト表現と、絶対値と偏角による極座標表現とを互いに変換する関数も提供しています。
共役複素数は、虚部の符号が反対の複素数です。
複素数ライブラリを使用する場合は、プログラムにヘッダーファイル complex.h をインクルードし、-lcomplex オプションまたは -library=complex オプションを使用してリンクしてください。
複素数ライブラリでは、クラス complex が 1 つだけ定義されています。クラス complex のオブジェクトは、1 つの複素数を持つことができます。複素数は次の 2 つの部分で構成されています。
実部
各部の数値は double 型で入っています。上は、クラス complex の定義の例です。
クラス complex のオブジェクトの値は、1 組の double 型の値です。最初の値が実部を表し、 2 番目の値が虚部を表します。
complex::complex() { re=0.0; im=0.0; } complex::complex(double r, double i = 0.0) { re=r; im=i; }
クラス complex には、2 つのコンストラクタがあります。上は、その定義です。
複素数の変数を引数なしで宣言すると、最初のコンストラクタが使用され、実部も虚部もゼロで初期化されます。次の例では、実部も虚部もゼロの複素数の変数が生成されます。
complex aComp;
引数は 1 つまたは 2 つ指定することができ、どちらの場合も 2 番目のコンストラクタが使用されます。次の例のように、引数を 1 つだけ指定した場合は、その値は実部の値とみなされ虚部はゼロに設定されます。
complex aComp(4.533);
4.533 + 0i
次の例のように、引数を 2 つ指定した場合は、最初の値が実部、2 番目の値が虚部となります。
complex aComp(8.999, 2.333);
8.999 + 2.333i
また、複素数ライブラリが提供する polar 関数を使用して複素数を生成することもできます (「数学関数」を参照してください)。polar 関数は、指定した 1 組の極座標値 (絶対値と偏角) を使用して複素数を作成します。
complex 型にはデストラクタはありません。
複素数ライブラリでは、すべての基本算術演算子が定義されています。特に、次の 5 つの演算子は通常の型の演算と同様に使用することができ、優先順序も同じです。
+ - / * =
演算子 - は、通常の型の場合と同様に 2 項演算子としても単項演算子としても使用できます。
この他、次の演算子の使用方法も通常の型で使用する演算子と同様です。
+= -= *= /=
complex a, b; ... if ((a+=2)==0) {...}; // 誤り b = a *= b; // 誤り
ただし、最後の 4 つの演算子では、式の中で使用できる値は生成されません。したがって、上のように使用することはできません。
また、等しいか否かを判定する次の 2 つの演算子は、通常の型で使用する演算子と同様に使用することができます。
== !=
算術式で実数と複素数が混在しているときは、 C++ では複素数のための演算子関数が使用され、実数は複素数に変換されます。
複素数ライブラリには、多くの数学関数が含まれています。複素数に特有のものもあれば、 C の標準数学ライブラリの関数と同じで複素数を対象にしたものもあります。
これらの関数はすべて、あらゆる可能な引数に対して結果を返します。関数が数学的に正しい結果を返せないような場合は、complex_error を呼び出して、何らかの適切な値を返します。たとえば、オーバーフローが実際に起こるのを避けるために complex_error を呼び出してメッセージを出します。次の表で複素数ライブラリの関数を説明します。
表 2-1 複素数ライブラリの関数
複素数ライブラリ関数 |
内容 |
---|---|
double abs(const complex) |
複素数の絶対値を返します。 |
double arg(const complex) |
複素数の偏角を返します。 |
complex conj(const complex) |
引数に対する共役複素数を返します。 |
double imag(const complex&) |
複素数の虚部を返します。 |
double norm(const complex) |
引数の絶対値の 2 乗を返します。abs より高速ですが、オーバーフローが起きやすくなります。絶対値の比較に使用します。 |
complex polar(double mag,double ang=0.0) |
複素数の絶対値と偏角を表す一組の極座標を引数として受け取り、それに対応する複素数を返します。 |
double real(const complex&) |
複素数の実部を返します。 |
表 2-2 複素数の数学関数と三角関数
複素数ライブラリ関数 |
内容 |
---|---|
complex acos(const complex) |
引数が余弦となるような角度を返します。 |
complex asin(const complex) |
引数が正弦となるような角度を返します。 |
complex atan(const complex) |
引数が正接となるような角度を返します。 |
complex cos(const complex) |
引数の余弦を返します。 |
complex cosh(const complex) |
引数の双曲線余弦を返します。 |
complex exp(const complex) |
e**x を計算します。ここで e は自然対数の底で、 x は関数 exp に渡された引数です。 |
complex log(const complex) |
引数の自然対数を返します。 |
complex log10(const complex) |
引数の常用対数を返します。 |
complex pow(double b, const complex exp) complex pow(const complex b, int exp) complex pow(const complex b, double exp) complex pow(const complex b, const complex exp) |
この関数は引数を 2 つ持ちます。 pow(b,exp) とすると、 b の exp 乗が計算されます。 |
complex sin(const complex) |
引数の正弦を返します。 |
complex sinh(const complex) |
引数の双曲線正弦を返します。 |
complex sqrt(const complex) |
引数の平方根を返します。 |
complex tan(const complex) |
引数の正接を返します。 |
complex tanh(const complex) |
引数の双曲線正接を返します。 |
extern int errno; class c_exception { ... }; int complex_error(c_exception&);
複素数ライブラリでは、エラー処理が上のように定義されています。
外部変数 errno は C ライブラリの大域的なエラー状態です。errno は、標準ヘッダー errno.h (perror(3) のマニュアルページを参照) にリストされている値を持ちます。 errno には、多くの関数でゼロ以外の値が設定されます。ある特定の演算でエラーが起こったかどうか調べるには、次のようにしてください。
errno をゼロに設定する。
演算終了後に値を調べる。
関数 complex_error は c_exception 型の参照引数を持ち、次に示す複素数ライブラリ関数に呼び出されます。
exp
log
log10
sinh
cosh
デフォルトの complex_error はゼロを返します。ゼロが返されたということは、デフォルトのエラー処理が実行されたということです。ユーザーは独自の complex_error 関数を作成して、別のエラー処理を行うことができます。エラー処理については、cplexrr(3C++) のマニュアルページで説明しています。
デフォルトのエラー処理については、cplxtrig(3C++) と cplxexp(3C++) のマニュアルページで説明しています。次に概要を示します。
表 2-3 複素数ライブラリ関数
複素数ライブラリ関数 |
デフォルトエラー処理 |
---|---|
exp |
オーバーフローが起こった場合は errno を ERANGE に設定し、最大複素数を返します。 |
log、log10 |
引数がゼロの場合は errno を EDOM に設定し、最大複素数を返します。 |
sinh、cosh |
引数の虚部によりオーバーフローが起こる場合は複素数ゼロを返します。引数の実部によりオーバーフローが起こる場合は最大複素数を返します。どちらの場合も errno は ERANGE に設定されます。 |
複素数ライブラリでは、次の例に示す複素数のデフォルトの抽出子と挿入子が提供されています。
ostream& operator<<(ostream&, const complex&); //挿入子 istream& operator>>(istream&, complex&) //抽出子
抽出子と挿入子の基本的説明については、「iostream 操作の基本構造」と 「iostream を使用した出力」を参照してください。
入力の場合、複素数の抽出子 >> は、(括弧の中にあり、コンマで区切られた) 一組の値を入力ストリームから抽出し、複素数オブジェクトに読み込みます。最初の値が実部の値、2 番目の値が虚部の値となります。たとえば、次のような宣言と入力文がある場合、(3.45,5) と入力すると、複素数 x の値は 3.45+5.0i となります。抽出子の場合はこの反対になります。complex x(3.45,5), cout << x の場合は、(3.45,5) と表示されます。
complex x; cin >> x;
入力データは、通常括弧の中でコンマで区切られた一組の値で、スペースは入れても入れなくてもかまいません。値を 1 つだけ入力したとき (括弧とスペースは入力してもしなくても同じ) は、抽出子は虚部をゼロとします。シンボル i を入力してはいけません。
挿入子は、複素数の実部と虚部をコンマで区切り、全体を括弧で囲んで挿入します。シンボル i は含まれません。2 つの値は double 型として扱われます。
complex 型は、組み込みの算術型と混在した式でも使用できるように定義されています。混合算術演算においては、算術型は自動的に complex 型に変換されます。算術演算子のすべてと数学関数のほとんどに対して、complex 型を使用できるバージョンが提供されています。次の例で考えてみます。
int i, j; double x, y; complex a, b; a = sin((b+i)/y) + x/j;
b+i という式は混合算術演算です。整数 i は、コンストラクタ complex::complex(double,double=0) によって、complex 型に変換されます (このとき、まず整数から double 型に変換されます)。b+i の計算結果を double 型の y で割っているので、y もまた complex 型に変換され、複素数除算演算が使用されます。商もまた complex 型ですので、複素数の正弦関数が呼び出され、その結果も complex 型になります。以下も同様です。
ただし、すべての算術演算と型変換が暗黙に行われるわけではありませんし、定義されていないものもあります。たとえば、複素数は数学的な意味での大小関係が決められないので、比較は等しいか否かの判定しかできません。
complex a, b; a == b // OK a != b // OK a < b // エラー:演算子 < は complex 型に使用できない a >= b // エラー:演算子 >= は complex 型に使用できない
同様に、complex 型からそれ以外の型への変換もはっきりした定義ができないので、そのような自動変換は行われません。変換するときは、実部または虚部を取り出すのか、または絶対値を取り出すのかを指定する必要があります。
complex a; double f(double); f(abs(a)); // OK f(a); // エラー: f(complex) は、引数の型が一致していない
クラス complex は効率も考慮して設計されています。
非常に簡単な関数が inline で宣言されており、関数呼び出しのオーバーヘッドをなくしています。
効率に差があるものは、関数が多重定義されています。たとえば、pow 関数には引数が complex 型のものの他に、引数が double 型と int 型のものがあります。その方が double 型と int 型の計算がはるかに簡単になるからです。
complex.h をインクルードすると、C の標準数学ライブラリヘッダー math.h も自動的にインクルードされます。C++ の多重定義の規則により、次のように最も効率の良い式の評価が行われます。
double x; complex x = sqrt(x);
この例では、標準数学関数 sqrt(double) が呼び出され、その計算結果が complex 型に変換されます。最初に complex 型に変換され、sqrt(complex) が呼び出されるのではありません。これは、多重定義の解決規則から決まる方法で、最も効率の良い方法です。
このほか、複素数ライブラリに関連するマニュアルページには以下のものがあります。
表 2-4 complex 型に関するマニュアルページ
マニュアルページ |
概要 |
---|---|
cplx.intro(3C++) |
複素数ライブラリ全体の紹介 |
cartpol(3C++) |
直角座標と極座標の関数 |
cplxerr(3C++) |
エラー処理関数 |
cplxexp(3C++) |
指数、対数、平方根の関数 |
cplxops(3C++) |
算術演算子関数 |
cplxtrig(3C++) |
三角関数 |