数値処理

C言語で複素数計算を解説:加減乗除と応用演算のサンプルコード紹介

このサンプルコードはC言語を使って複素数計算を行う方法を解説しています。

加算、減算、乗算、除算などの基本演算に加え、複素数を活用した応用的な計算例も含まれており、具体的なコードを通して実装方法を学ぶことができます。

C言語で複素数を扱う際の参考にしてください。

複素数の基本

複素数は実数部と虚数部で構成され、a+biの形式で表されます。

以下では、C言語において複素数を実装する2通りの方法について紹介します。

複素数の定義と表現方法

複素数を扱う際は、オリジナルの構造体を定義する方法と、C言語標準の<complex.h>を利用する方法があります。

状況に応じて使い分けることで、柔軟な実装が可能です。

構造体を用いた実装手法

独自の構造体を定義することで、複素数の各要素(実部、虚部)を明示的に管理できます。

例えば以下のコードでは、Complex構造体を定義し、加算を行う関数を実装しています。

#include <stdio.h>
typedef struct {
    double real; // 複素数の実部
    double imag; // 複素数の虚部
} Complex;
// 複素数の加算を行う関数
Complex addComplex(Complex a, Complex b) {
    Complex result;
    result.real = a.real + b.real;
    result.imag = a.imag + b.imag;
    return result;
}
int main(void) {
    Complex num1 = {1.0, 2.0}; // 複素数 1+2i
    Complex num2 = {3.0, 4.0}; // 複素数 3+4i
    Complex sum = addComplex(num1, num2);
    printf("和 = %f + %fi\n", sum.real, sum.imag);
    return 0;
}
和 = 4.000000 + 6.000000i

このように、構造体を使った実装では、各計算関数が明確に定義され、読みやすいコードとなります。

<complex.h> を用いた実装手法

C99以降で標準ヘッダ<complex.h>が実装され、複素数を直接扱えるようになりました。

標準ライブラリを利用すると、複素数の変数はdouble complex型で定義でき、creal()cimag()といった関数を利用して実部や虚部を取得できます。

#include <stdio.h>
#include <complex.h>
int main(void) {
    double complex z1 = 1.0 + 2.0 * I; // 複素数 1+2i
    double complex z2 = 3.0 + 4.0 * I; // 複素数 3+4i
    double complex sum = z1 + z2;
    // creal()とcimag()で実部と虚部を取得
    printf("和 = %f + %fi\n", creal(sum), cimag(sum));
    return 0;
}
和 = 4.000000 + 6.000000i

<complex.h>を利用する方法は、標準化された関数が揃っているため、簡潔な実装が可能です。

基本演算の実装例

基本的な演算として、複素数の加算、減算、乗算、除算を行います。

ここでは、構造体を用いた実装例により、その手法を確認していきます。

複素数の加算

複素数の加算は、各々の実部と虚部を足し合わせることで計算できます。

下記のサンプルコードでは、addComplex()関数により加算を実装しています。

#include <stdio.h>
typedef struct {
    double real; // 実部
    double imag; // 虚部
} Complex;
// 複素数加算関数
Complex addComplex(Complex a, Complex b) {
    Complex result;
    result.real = a.real + b.real;
    result.imag = a.imag + b.imag;
    return result;
}
int main(void) {
    Complex num1 = {2.0, 3.0}; // 2 + 3i
    Complex num2 = {1.5, 4.0}; // 1.5 + 4i
    Complex sum = addComplex(num1, num2);
    printf("加算結果 = %f + %fi\n", sum.real, sum.imag);
    return 0;
}
加算結果 = 3.500000 + 7.000000i

複素数の減算

減算は、加算と同様に実部と虚部ごとに引き算します。

下記のコードでは、subComplex()関数を利用して減算の実装例を示します。

#include <stdio.h>
typedef struct {
    double real; // 実部
    double imag; // 虚部
} Complex;
// 複素数減算関数
Complex subComplex(Complex a, Complex b) {
    Complex result;
    result.real = a.real - b.real;
    result.imag = a.imag - b.imag;
    return result;
}
int main(void) {
    Complex num1 = {5.0, 6.0}; // 5+6i
    Complex num2 = {2.0, 3.0}; // 2+3i
    Complex diff = subComplex(num1, num2);
    printf("減算結果 = %f + %fi\n", diff.real, diff.imag);
    return 0;
}
減算結果 = 3.000000 + 3.000000i

複素数の乗算

乗算は、以下の数式で計算されます。

(a+bi)(c+di)=(acbd)+(ad+bc)i

下記のサンプルコードでは、multiplyComplex()関数により乗算の実装例を示します。

#include <stdio.h>
typedef struct {
    double real;
    double imag;
} Complex;
// 複素数乗算関数
Complex multiplyComplex(Complex a, Complex b) {
    Complex result;
    result.real = a.real * b.real - a.imag * b.imag; // 実部の計算
    result.imag = a.real * b.imag + a.imag * b.real; // 虚部の計算
    return result;
}
int main(void) {
    Complex num1 = {2.0, 3.0}; // 2+3i
    Complex num2 = {4.0, 5.0}; // 4+5i
    Complex product = multiplyComplex(num1, num2);
    printf("乗算結果 = %f + %fi\n", product.real, product.imag);
    return 0;
}
乗算結果 = -7.000000 + 22.000000i

複素数の除算

複素数の除算は、分母に複素数の共役をかけることで実数化し、その後計算を行います。

以下のコードでは、divideComplex()関数で実装例を示しています。

ここでは分母の0除算に注意する必要があります。

#include <stdio.h>
typedef struct {
    double real;
    double imag;
} Complex;
// 複素数除算関数(分母が0でないことを前提としています)
Complex divideComplex(Complex a, Complex b) {
    double denom = b.real * b.real + b.imag * b.imag; // \( \text{denom} = c^2 + d^2 \)
    Complex result;
    result.real = (a.real * b.real + a.imag * b.imag) / denom;
    result.imag = (a.imag * b.real - a.real * b.imag) / denom;
    return result;
}
int main(void) {
    Complex num1 = {7.0, 5.0}; // 7+5i
    Complex num2 = {2.0, -3.0}; // 2-3i
    Complex quotient = divideComplex(num1, num2);
    printf("除算結果 = %f + %fi\n", quotient.real, quotient.imag);
    return 0;
}
除算結果 = -1.000000 + 3.000000i

応用的な演算例

基本演算に加え、複素数の極形式変換やべき乗演算など、応用的な計算も実装できます。

以下に、変換や計算のサンプルコードを示します。

複素数の極形式変換

複素数を極形式に変換するには、複素数 z=a+bi の大きさ r と偏角 θ を求めます。

r=a2+b2

θ=arctanba

下記のコードは、構造体を用いて極形式への変換を行う例です。

#include <stdio.h>
#include <math.h>
typedef struct {
    double real;
    double imag;
} Complex;
int main(void) {
    Complex z = {3.0, 4.0}; // 3+4i
    double r = sqrt(z.real * z.real + z.imag * z.imag);    // \( r = \sqrt{3^2+4^2} \)
    double theta = atan2(z.imag, z.real);                  // \( \theta = \arctan\frac{4}{3} \)
    printf("極形式: r = %f, θ = %f (ラジアン)\n", r, theta);
    return 0;
}
極形式: r = 5.000000, θ = 0.927295 (ラジアン)

複素数の絶対値と偏角の算出

複素数の絶対値は、その大きさ r と同じであり、偏角はその角度 θ です。

以下のコードでは、これらを求める関数を実装して算出しています。

#include <stdio.h>
#include <math.h>
typedef struct {
    double real;
    double imag;
} Complex;
// 複素数の絶対値の計算
double absComplex(Complex a) {
    return sqrt(a.real * a.real + a.imag * a.imag);
}
// 複素数の偏角の計算
double angleComplex(Complex a) {
    return atan2(a.imag, a.real);
}
int main(void) {
    Complex z = {5.0, 12.0}; // 5+12i
    double absValue = absComplex(z);
    double angle = angleComplex(z);
    printf("絶対値 = %f\n", absValue);
    printf("偏角 = %f (ラジアン)\n", angle);
    return 0;
}
絶対値 = 13.000000
偏角 = 1.176005 (ラジアン)

複素数のべき乗計算

複素数のべき乗計算は、De Moivreの定理を利用して実装できます。

De Moivreの定理では、zn=rn(cos(nθ)+isin(nθ))と表されます。

下記のサンプルコードは、入力された複素数のn乗を計算する例です。

#include <stdio.h>
#include <math.h>
typedef struct {
    double real;
    double imag;
} Complex;
// 複素数のべき乗計算(De Moivreの定理を利用)
Complex powerComplex(Complex z, int n) {
    Complex result;
    // 複素数の極形式への変換
    double r = sqrt(z.real * z.real + z.imag * z.imag);
    double theta = atan2(z.imag, z.real);
    // べき乗計算:\( r^n \) と \( n\theta \)
    double r_n = pow(r, n);
    double angle_n = theta * n;
    // 直交形式に変換
    result.real = r_n * cos(angle_n);
    result.imag = r_n * sin(angle_n);
    return result;
}
int main(void) {
    Complex z = {1.0, 1.0}; // 1+1i
    int n = 3;
    Complex result = powerComplex(z, n);
    printf("べき乗計算結果 = %f + %fi\n", result.real, result.imag);
    return 0;
}
べき乗計算結果 = -2.000000 + 2.000000i

サンプルコード解説のポイント

C言語で複素数計算を実装する際のサンプルコードは、コード構成と関数の役割分担が明確になっている点が特徴です。

以下では、コードの構成や実装内容をわかりやすく解説します。

コード構成と各関数の役割

サンプルコードでは、複素数の演算ごとに関数を分けることで、以下の点が実現されています。

  • 保守性が高い:各計算が独立して実装され、必要に応じて再利用できるようになっています。
  • 読みやすさ:関数名がその役割を明示しており、全体の流れを理解しやすい構成となっています。
  • 拡張性:複素数演算を追加する場合でも、同様の形式で関数を実装することで対応可能です。

コメントと実装内容の対応

コード内のコメントは、実装している部分ごとにその意味や計算式を示しており、以下のような点に留意しています。

  • 変数名や関数名は英語表記として統一しており、コメント内で日本語の解説を加えることで、初学者にも理解しやすい工夫がされています。
  • 数式はLATEX形式で記述され、対応するコード部分との整合性が取れています。

エラーハンドリングと注意点

複素数の除算など、一部の計算においてはエラーハンドリングが重要です。

特に以下の点に注意する必要があります。

  • 分母が0となる場合:除算関数では、分母が0に近い場合の対策(例:エラーチェックや例外処理)を実装することで、プログラムの不具合を防ぐ必要があります。
  • 入力値の妥当性:極形式変換やべき乗計算では、入力された複素数の値が妥当な範囲にあることを確認することが望ましいです。

上記のポイントを踏まえ、コードに適切なコメントやチェックを加えることで、読みやすく保守しやすい実装となっています。

まとめ

この記事では、C言語を用いて複素数の定義や表現方法、基本的な加減乗除と極形式変換、絶対値・偏角、べき乗計算などの応用演算の実装例を紹介しています。

構造体や<complex.h>を利用したサンプルコードと、その分かりやすいコメントにより、各関数の役割や実装の流れが理解できる内容となっています。

関連記事

Back to top button
目次へ