VisualC++ と g++ における complexクラスの挙動の違い
仮想物理実験室で行なっている数値計算は、Windows上のVisualC++でデバックを行った後に、UNIX上の g++ で実行しています。 その際に2つの実行環境にて計算結果が違うという困ったことが起きたので、メモしておきます。
表題にある「complexクラス」とは、C++に用意されている Standard Template Library (STL)と呼ばれる標準クラスライブラリで、複素数を用いた演算を行う際に利用することができます。complex型の変数 z に 複素数を代入するには
complex<double> z = complex<double>( 1.0, 2.0 );
とします。そこで、complex型の変数で
という演算をさせたいとします。 計算結果はとなるわけですが、VisualC++ と g++ で異なる結果となってしまうことに気が付きました。 具体的に、2種類の代入の仕方を考えます。
complex<double> a = sqrt( 1.0 - complex<double>(5.0,0));
complex<double> b = sqrt( complex<double>(1.0,0.0) - complex<double>(5.0,0));
上記の2つの値を VisualC++ と g++ で出力した結果(プログラムソースは下をご覧ください)は
■ VisualC++
■ g++
となり、VisualC++ では変数 a と b の値は正しい結果を得られますが、 g++ では変数 a の値が間違った値となっていることがわかります。 つまり、a の方法はコンパイラによっては良くないということがわかります。 原因として考えられるのは、キャストの振る舞いの違いです。 その理由は、a と b の違いが、実数 1.0 の表現を、実数型として与えているか複素数型として与えているかだからです。 コンパイラの専門家ではないのでこれ以上はわからないですが、 実数型変数を複素数型変数への代入を考える場合には、複素数型への明示的なキャストを行ったほうがよいということがわかりました。
C++プログラムソース
/* VisualC++ と g++ における complexクラスの挙動の違い (2011.12.11公開) */ #include <math.h> #include <iostream> #include <complex> using namespace std; int main(){ complex<double> a = sqrt( 1.0 - complex<double>(5.0,0)); complex<double> b = sqrt( complex<double>(1.0,0.0) - complex<double>(5.0,0)); cout << "比較 " << a << " " << b << endl; cin.get(); }