Cで複素数を処理する方法は?


122

Cで複素数を処理するにはどうすればよいですか?私はそこにある参照complex.hヘッダファイルが、それは私にそれを使用する方法についての多くの情報を与えるものではありません。効率的な方法で実数部と虚数部にアクセスする方法は?モジュールとフェーズを取得するネイティブ関数はありますか?


16
Pythonコードにバインドする方が簡単なので、C ++ではなくCを使用しています。
Charles Brunet、2011年

回答:


186

このコードはあなたを助けるでしょう、そしてそれはかなり自明です:

#include <stdio.h>      /* Standard Library of Input and Output */
#include <complex.h>    /* Standard Library of Complex Numbers */

int main() {

    double complex z1 = 1.0 + 3.0 * I;
    double complex z2 = 1.0 - 4.0 * I;

    printf("Working with complex numbers:\n\v");

    printf("Starting values: Z1 = %.2f + %.2fi\tZ2 = %.2f %+.2fi\n", creal(z1), cimag(z1), creal(z2), cimag(z2));

    double complex sum = z1 + z2;
    printf("The sum: Z1 + Z2 = %.2f %+.2fi\n", creal(sum), cimag(sum));

    double complex difference = z1 - z2;
    printf("The difference: Z1 - Z2 = %.2f %+.2fi\n", creal(difference), cimag(difference));

    double complex product = z1 * z2;
    printf("The product: Z1 x Z2 = %.2f %+.2fi\n", creal(product), cimag(product));

    double complex quotient = z1 / z2;
    printf("The quotient: Z1 / Z2 = %.2f %+.2fi\n", creal(quotient), cimag(quotient));

    double complex conjugate = conj(z1);
    printf("The conjugate of Z1 = %.2f %+.2fi\n", creal(conjugate), cimag(conjugate));

    return 0;
}

  と:

creal(z1)実数部を取得する(floatのcrealf(z1)場合、long doubleの場合creall(z1)

cimag(z1)虚数部を取得する(floatのcimagf(z1)場合、long doubleの場合cimagl(z1)

複素数を扱うときに覚えておくべきもう一つの重要な点は、関数が好きということですcos()exp()そしてsqrt()例えば、その複雑な形状に置き換える必要がありますccos()cexp()csqrt()


12
これは何double complexですか?これは言語拡張ですか、それともマクロマジックですか?
Calmarius 14

@Calmarius complexは標準のc99型です(GCCの内部では、実際には_Complex型のエイリアスです)。
スナイプ、2015

9
@Snaipe:complexはタイプではありません。これ_Complexは、型指定子であるに展開されるマクロですが、それ自体は型ではありません。複雑なタイプがありfloat _Complexdouble _Complexlong double _Complex
キース・トンプソン

3
これはGCCだけでなく、_Complexが型指定子であり、complex.hが_Complexに展開する複雑なマクロを持っていることが標準で定義されています。_Boolとstdbool.hについても同様です。
jv110 2018

40

複合型は、C99標準(-std=c99GCCのオプション)以降のC言語です。一部のコンパイラは、以前のモードでも複雑な型を実装している場合がありますが、これは非標準で移植性のない拡張です(例:IBM XL、GCC、インテルなど)。

あなたはhttp://en.wikipedia.org/wiki/Complex.hから始めることができます-それはcomplex.hからの機能の説明を与えます

このマニュアルhttp://pubs.opengroup.org/onlinepubs/009604499/basedefs/complex.h.htmlには、マクロに関する情報も記載されています。

複合変数を宣言するには、次を使用します

  double _Complex  a;        // use c* functions without suffix

または

  float _Complex   b;        // use c*f functions - with f suffix
  long double _Complex c;    // use c*l functions - with l suffix

値を複素数にするには、次の_Complex_Iマクロを使用しますcomplex.h

  float _Complex d = 2.0f + 2.0f*_Complex_I;

(実際には(0,-0i)、複素数の半分の数値とNaNに問題がある可能性があります)

モジュールはcabs(a)/ cabsl(c)/ cabsf(b); 実部はcreal(a)、架空のものですcimag(a)carg(a)複雑な議論のためのものです。

実際のimagパーツに直接アクセス(読み取り/書き込み)するには、この移植 できないGCC拡張機能を使用できます。

 __real__ a = 1.4;
 __imag__ a = 2.0;
 float b = __real__ a;

1
ほぼすべての複雑な関数は、組み込み関数として効率的な方法でコンパイラーによって実装されます。最新のコンパイラを使用して、ゼロ以外のレベルの最適化を行います。
osgx

3
参考までに、OPはPythonバインディングについて言及しているため、Pythonで作業するときはC89を使用するようにします(Pythonの残りのコードはC89であるため、拡張機能をWindowsで実行する場合は、通常、MVSCでコンパイルされます。 C89)。絶対に必要なのかはわかりません。
13

1
この式(complex float) { r, i }を使用して、数値の個別の部分を個別に設定することもできます(たとえば、虚数部がNANであるときに実数部をINFにすることができます)。これはGCC固有のキーワードを回避しますが、実際に移植可能かどうかはわかりません。
クロン14

2
C99ではComplexサポートはオプションであることに注意してください。コンパイラがを定義している場合、コンパイラはサポートしていない可能性があります__STDC_NO_COMPLEX__。ただし、実際には、主要なコンパイラに実装されています。
Ciro Santilli郝海东冠状病六四事件法轮功

1
Jasen、N1256ドラフトopen-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf#page=182「7.3複雑な算術<complex.h>」の182ページを確認してください。そのようなキーワードは、複雑なものを手作業で実装する既存のc(C90)プログラムを壊さないように、C99で選択された可能性があります。<complex.h>が含まれている場合complex、マクロとして定義され、に展開され_Complexます。(2008)ページ500「複合型」:あなたはまた、デレク・M.ジョーンズの「アン経済文化解説新C標準」に興味がある可能性がありpeople.ece.cornell.edu/land/courses/ece4760/...
osgx

9

Complex.h

#include <stdio.h>      /* Standard Library of Input and Output */
#include <complex.h>    /* Standart Library of Complex Numbers */

int main() 
{
    double complex z1 = 1.0 + 3.0 * I;
    double complex z2 = 1.0 - 4.0 * I;

    printf("Working with complex numbers:\n\v");

    printf("Starting values: Z1 = %.2f + %.2fi\tZ2 = %.2f %+.2fi\n", 
           creal(z1), 
           cimag(z1), 
           creal(z2), 
           cimag(z2));

    double complex sum = z1 + z2;
    printf("The sum: Z1 + Z2 = %.2f %+.2fi\n", creal(sum), cimag(sum));
}

4

便宜上、tgmath.hタイプ生成マクロのライブラリを含めることができます。すべてのタイプの変数のdoubleバージョンと同じ関数名を作成します。例えば、例えば、それは定義sqrt()に展開されるマクロsqrtf()sqrt()またはsqrtl()提供される引数の種類に応じて、機能。

したがって、さまざまなタイプの変数に対応する関数名を覚えておく必要はありません。

#include <stdio.h>
#include <tgmath.h>//for the type generate macros. 
#include <complex.h>//for easier declare complex variables and complex unit I

int main(void)
{
    double complex z1=1./4.*M_PI+1./4.*M_PI*I;//M_PI is just pi=3.1415...
    double complex z2, z3, z4, z5; 

    z2=exp(z1);
    z3=sin(z1);
    z4=sqrt(z1);
    z5=log(z1);

    printf("exp(z1)=%lf + %lf I\n", creal(z2),cimag(z2));
    printf("sin(z1)=%lf + %lf I\n", creal(z3),cimag(z3));
    printf("sqrt(z1)=%lf + %lf I\n", creal(z4),cimag(z4));
    printf("log(z1)=%lf + %lf I\n", creal(z5),cimag(z5));

    return 0;
}

2

複素数の概念は、負の二次根を計算する必要性から、数学に導入されました。複素数の概念は、さまざまなエンジニアリング分野で採用されました。

今日、その複素数は、物理学、電子工学、力学、天文学などの高度なエンジニアリング分野で広く使用されています...

負の平方根の例の実数部と虚数部:

#include <stdio.h>   
#include <complex.h>

int main() 
{
    int negNum;

    printf("Calculate negative square roots:\n"
           "Enter negative number:");

    scanf("%d", &negNum);

    double complex negSqrt = csqrt(negNum);

    double pReal = creal(negSqrt);
    double pImag = cimag(negSqrt);

    printf("\nReal part %f, imaginary part %f"
           ", for negative square root.(%d)",
           pReal, pImag, negNum);

    return 0;
}

-1

複素数値式の実部を抽出するzには、表記としてasを使用し__real__ zます。同様に、の__imag__属性を使用しzて虚数部を抽出します。

例えば;

__complex__ float z;
float r;
float i;
r = __real__ z;
i = __imag__ z;

rは複素数 "z"の実部iは複素数 "z"の虚部


2
これらはgcc固有の拡張機能です。もう一つの答えは、すでにそれらを述べた、と受け入れ答え標準Cでこれを行う方法をすでに
キース・トンプソン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.