Sun Studio 12: C++ ユーザーズガイド

第 15 章 複素数演算ライブラリの使用

複素数には「実部」と「虚部」があります。次に例を示します。

3.2 + 4i 1 + 3i 1 + 2.3i

通常は、0 + 3i のように完全に虚部だけのものは通常 3i と書き、5 + 0i のように完全に実部だけのものは通常 5 と書きます。データ型 complex を使用すると複素数を表現できます。


注 –

複素数ライブラリ (libcomplex) は互換モードでのみ使用できます (-compat[=4])。 標準モード (デフォルトのモード) では、同様の機能を持つ複素数クラスが C++ 標準ライブラリ (libCstd) に含まれています。


15.1 複素数ライブラリ

複素数ライブラリは、 新しいデータ型として複素数データ型を実装します。このライブラリには次のものが含まれています。

複素数には、実部と虚部による表現方法のほかに、 絶対値と偏角による表現方法があります。複素数ライブラリには、実部と虚部によるデカルト表現と、絶対値と偏角による極座標表現とを互いに変換する関数も提供しています。

共役複素数は、虚部の符号が反対の複素数です。

15.1.1 複素数ライブラリの使用方法

複素数ライブラリを使用する場合は、プログラムにヘッダーファイル c omplex.h をインクルードし、-lcomplex オプションまたは -library=complex オプションを使用してリンクしてください。

15.2 complex 型

複素数ライブラリでは、クラス complex が 1 つだけ定義されています。クラス complex のオブジェクトは、1 つの複素数を持つことができます。複素数は次の 2 つの部分で構成されています。


class complex {
    double re, im;
};

クラス complex のオブジェクトの値は、1 組の double 型の値です。最初の値が実部を表し、2 番目の値が虚部を表します。

15.2.1 complex クラスのコンストラクタ

complex には 2 つのコンストラクタがあります。それぞれの定義を次に示します。


complex::complex()            {re=0.0; im=0.0;}
complex::complex(double r, double i = 0.0) {re=r; im=i;}

複素数の変数を引数なしで宣言すると、最初のコンストラクタが使用され、実部も虚部もゼロで初期化されます。次の例では、実部も虚部もゼロの複素数の変数が生成されます。


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 関数を使用して複素数を生成することもできます。「15.3 数学関数」を参照してください。polar 関数は、指定した 1 組の極座標値 (絶対値と偏角) を使用して複素数を作成します。

complex 型にはデストラクタはありません。

15.2.2 算術演算子

複素数ライブラリでは、すべての基本算術演算子が定義されています。特に、次の 5 つの演算子は通常の型の演算と同様に使用することができ、優先順序も同じです。

+ - / * =

演算子 - は、通常の型の場合と同様に 2 項演算子としても単項演算子としても使用できます。

このほか、次の演算子の使用方法も通常の型で使用する演算子と同様です。

ただし、この 4 つの演算子については、式の中で使用可能な値は生成されません。したがって、次のコードは機能しません。


complex a, b;
...
if ((a+=2)==0) {...}; // 誤り
b = a *= b; // 誤り

また、等しいか否かを判定する 2 つの演算子 (==!=) は、通常の型で使用する演算子と同様に使用することができます。

算術式で実数と複素数が混在しているときは、C++ では複素数のための演算子関数が使用され、実数は複素数に変換されます。

15.3 数学関数

複素数ライブラリには、多くの数学関数が含まれています。複素数に特有のものもあれば、 C の標準数学ライブラリの関数と同じで複素数を対象にしたものもあります。

これらの関数はすべて、あらゆる可能な引数に対して結果を返します。関数が数学的に正しい結果を返せないような場合は、complex_error を呼び出して、何らかの適切な値を返します。たとえば、オーバーフローが実際に起こるのを避けるために complex_error を呼び出してメッセージを出します。次の表で複素数ライブラリの関数を説明します。


注 –

sqrt 関数と atan2 関数は、C99 の csqrt (Annex G) の仕様に従って実装されています。


表 15–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&)

複素数の実部を返します。 

表 15–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). bexp 乗します。

complex sin(const complex)

引数の正弦を返します。 

complex sinh(const complex)

引数の双曲線正弦を返します。 

complex sqrt(const complex)

引数の平方根を返します。 

complex tan(const complex)

引数の正接を返します。 

complex tanh(const complex)

引数の双曲線正接を返します。 

15.4 エラー処理

複素数ライブラリでは、エラー処理が次のように定義されています。


extern int errno;
class c_exception {...};
int complex_error(c_exception&);

外部変数 errno は C ライブラリの大域的なエラー状態です。errno は、標準ヘッダー errno.h (perror(3) のマニュアルページを参照) にリストされている値を持ちます。errno には、多くの関数でゼロ以外の値が設定されます。

ある特定の演算でエラーが起こったかどうか調べるには、次のようにしてください。

  1. 演算実行前に errno をゼロに設定する。

  2. 演算終了後に値を調べる。

関数 complex_errorc_exception 型の参照引数を持ち、次に示す複素数ライブラリ関数に呼び出されます。

デフォルトの complex_error はゼロを返します。ゼロが返されたということは、デフォルトのエラー処理が実行されたということです。ユーザーは独自の complex_error 関数を作成して、別のエラー処理を行うことができます。エラー処理については、cplxerr(3CC4) のマニュアルページで説明しています。

デフォルトのエラー処理については、cplxtrig(3CC4) と cplxexp(3CC4) のマニュアルページを参照してください。 次の表にも、その概要を掲載しています。

複素数ライブラリ関数 

デフォルトエラー処理 

exp

オーバーフローが起こった場合は errno ERANGE に設定し、最大複素数を返します。

log、log10

引数がゼロの場合は errno EDOM に設定し、最大複素数を返します。

sinh、cosh

引数の虚部によりオーバーフローが起こる場合は複素数ゼロを返します。引数の実部によりオーバーフローが起こる場合は最大複素数を返します。どちらの場合も errnoERANGE に設定されます。

15.5 入出力

複素数ライブラリでは、次の例に示す複素数のデフォルトの抽出子と挿入子が提供されています。


ostream& operator<<(ostream&, const complex&); // 挿入子
istream& operator>>(istream&, complex&); // 抽出子

抽出子と挿入子の基本的な説明については、「14.2 iostream 操作の基本構造」「14.3.1 iostream を使用した出力」を参照してください。

入力の場合、複素数の抽出子 >> は、(括弧の中にあり、コンマで区切られた) 一組の値を入力ストリームから抽出し、複素数オブジェクトに読み込みます。最初の値が実部の値、 2 番目の値が虚部の値となります。たとえば、次のような宣言と入力文がある場合、


complex x;
cin >> x;

(3.45, 5) と入力すると、複素数 x の値は 3.45 + 5.0i となります。抽出子の場合はこの反対になります。complex x(3.45, 5), cout<<x の場合は、(3.45, 5) と表示されます。

入力データは、通常括弧の中でコンマで区切られた一組の値で、スペースは入れても入れなくてもかまいません。値を 1 つだけ入力したとき (括弧とスペースは入力してもしなくても同じ) は、抽出子は虚部をゼロとします。シンボル i を入力してはいけません。

挿入子は、複素数の実部と虚部をコンマで区切り、全体を括弧で囲んで挿入します。シンボル i は含まれません。2 つの値は double 型として扱われます。

15.6 混合演算

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) は、引数の型が一致していない

15.7 効率

クラス 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) が呼び出されるのではありません。これは、多重定義の解決規則から決まる方法で、もっとも効率の良い方法です。

15.8 複素数のマニュアルページ

複素数演算ライブラリの情報は、次のマニュアルページに記載されています。

表 15–3 complex 型のマニュアルページ

マニュアルページ 

概要 

cplx.intro(3CC4)

複素数ライブラリ全体の紹介 

cartpol(3CC4)

直角座標と極座標の関数 

cplxerr(3CC4)

エラー処理関数 

cplxexp(3CC4)

指数、対数、平方根の関数 

cplxops(3CC4)

算術演算子関数 

cplxtrig(3CC4)

三角関数