C++標準ライブラリで数値演算を行う方法

C++の標準ライブラリは、数値演算において強力なツールを提供します。本記事では、基本的な演算から複雑な数値操作までをカバーし、標準ライブラリの活用方法を詳しく解説します。具体的なコード例を通じて、実践的な理解を深めることができます。

目次

数値演算に使用する標準ライブラリの概要

C++の標準ライブラリは、数値演算を効率的に行うための多様な機能を提供します。これには、基本的な算術演算、数学関数、乱数生成、複素数演算、線形代数などが含まれます。これらのライブラリを活用することで、複雑な数値操作を簡単に実装できるようになります。

基本的な算術演算

標準ライブラリでは、加算、減算、乗算、除算といった基本的な算術演算が容易に行えます。これらは通常の演算子(+、-、*、/)で実装されます。

数学関数の使用

cmathライブラリには、三角関数、指数関数、対数関数など、多くの数学関数が含まれています。これにより、複雑な数値計算をシンプルに実装できます。

乱数生成

標準ライブラリには、乱数を生成するためのさまざまな機能が含まれています。これにより、ランダムな数値やシミュレーションを行うことが可能です。

複素数演算

complexライブラリを使用することで、複素数の演算が簡単に行えます。これは、科学技術計算や工学の分野で特に有用です。

線形代数の基本

標準ライブラリには、線形代数の基本的な操作をサポートする機能も含まれています。ベクトルや行列の計算を効率的に行うことができます。

基本的な数値演算

C++の標準ライブラリを用いた基本的な数値演算は、プログラムの基本となる操作です。加算、減算、乗算、除算など、日常的に使用される基本的な演算を理解し、実際のコードでどのように使用されるかを見ていきましょう。

加算

加算は、2つの数値を足し合わせる基本的な操作です。C++では、+ 演算子を使用して実行します。

#include <iostream>
int main() {
    int a = 5;
    int b = 3;
    int sum = a + b;
    std::cout << "Sum: " << sum << std::endl;
    return 0;
}

減算

減算は、1つの数値から別の数値を引く操作です。- 演算子を使用して実行します。

#include <iostream>
int main() {
    int a = 5;
    int b = 3;
    int difference = a - b;
    std::cout << "Difference: " << difference << std::endl;
    return 0;
}

乗算

乗算は、2つの数値を掛け合わせる操作です。* 演算子を使用して実行します。

#include <iostream>
int main() {
    int a = 5;
    int b = 3;
    int product = a * b;
    std::cout << "Product: " << product << std::endl;
    return 0;
}

除算

除算は、1つの数値を別の数値で割る操作です。/ 演算子を使用して実行します。ただし、整数の除算は整数結果を返すため、注意が必要です。

#include <iostream>
int main() {
    int a = 6;
    int b = 3;
    int quotient = a / b;
    std::cout << "Quotient: " << quotient << std::endl;
    return 0;
}

剰余

剰余演算は、1つの数値を別の数値で割った余りを求める操作です。% 演算子を使用して実行します。

#include <iostream>
int main() {
    int a = 7;
    int b = 3;
    int remainder = a % b;
    std::cout << "Remainder: " << remainder << std::endl;
    return 0;
}

浮動小数点演算

浮動小数点演算は、C++において非常に重要な役割を果たします。これは特に、科学技術計算やグラフィックス処理において広く利用されます。C++では、浮動小数点数を扱うために floatdoublelong double の3つのデータ型が提供されています。

基本的な浮動小数点演算

浮動小数点数を用いた基本的な演算は、整数の場合と同様に行われます。以下の例では、double 型の変数を使用して加算、減算、乗算、除算を行います。

#include <iostream>
int main() {
    double a = 5.5;
    double b = 3.2;

    double sum = a + b;
    double difference = a - b;
    double product = a * b;
    double quotient = a / b;

    std::cout << "Sum: " << sum << std::endl;
    std::cout << "Difference: " << difference << std::endl;
    std::cout << "Product: " << product << std::endl;
    std::cout << "Quotient: " << quotient << std::endl;

    return 0;
}

精度の違い

floatdoublelong double はそれぞれ異なる精度を持ちます。float は単精度浮動小数点数、double は倍精度浮動小数点数、long double はさらに高精度な浮動小数点数を表します。

#include <iostream>
#include <iomanip> // for std::setprecision

int main() {
    float f = 3.14159265358979323846f;
    double d = 3.14159265358979323846;
    long double ld = 3.14159265358979323846L;

    std::cout << std::setprecision(20);
    std::cout << "float: " << f << std::endl;
    std::cout << "double: " << d << std::endl;
    std::cout << "long double: " << ld << std::endl;

    return 0;
}

浮動小数点の誤差

浮動小数点数は、有限のビット数で数を表すため、誤差が生じることがあります。これにより、特定の計算において精度が失われることがあります。

#include <iostream>
int main() {
    double a = 0.1;
    double b = 0.2;
    double sum = a + b;

    if (sum == 0.3) {
        std::cout << "Sum is exactly 0.3" << std::endl;
    } else {
        std::cout << "Sum is not exactly 0.3" << std::endl;
    }

    return 0;
}

この例では、0.1 + 0.20.3 ではないと判断される場合があります。これは、浮動小数点数の表現における精度の限界によるものです。

数学関数の利用

C++の標準ライブラリには、さまざまな数学関数が用意されています。これらの関数は、数学的な計算を簡単に行うためのものです。cmathライブラリを利用することで、複雑な数学演算も容易に実装できます。

三角関数

三角関数は、角度を入力としてサイン、コサイン、タンジェントなどの値を計算します。以下に、sincostan関数の使用例を示します。

#include <iostream>
#include <cmath>

int main() {
    double angle = 45.0;
    double radians = angle * M_PI / 180.0; // 度をラジアンに変換

    std::cout << "sin(45°) = " << sin(radians) << std::endl;
    std::cout << "cos(45°) = " << cos(radians) << std::endl;
    std::cout << "tan(45°) = " << tan(radians) << std::endl;

    return 0;
}

指数関数と対数関数

指数関数(exp)と対数関数(loglog10)は、数学的な計算において頻繁に使用されます。以下にその使用例を示します。

#include <iostream>
#include <cmath>

int main() {
    double value = 2.0;

    std::cout << "exp(2) = " << exp(value) << std::endl;
    std::cout << "log(2) = " << log(value) << std::endl; // 自然対数
    std::cout << "log10(2) = " << log10(value) << std::endl; // 常用対数

    return 0;
}

平方根と累乗

平方根を計算するためのsqrt関数と、数を累乗するためのpow関数もよく使われます。

#include <iostream>
#include <cmath>

int main() {
    double value = 16.0;

    std::cout << "sqrt(16) = " << sqrt(value) << std::endl;
    std::cout << "2^3 = " << pow(2.0, 3.0) << std::endl;

    return 0;
}

絶対値関数

fabs関数を使って浮動小数点数の絶対値を計算することができます。

#include <iostream>
#include <cmath>

int main() {
    double value = -3.5;

    std::cout << "fabs(-3.5) = " << fabs(value) << std::endl;

    return 0;
}

これらの関数を組み合わせることで、複雑な数値計算を効率的に行うことができます。

乱数生成

乱数生成は、多くのプログラムで必要とされる操作です。C++の標準ライブラリには、乱数を生成するためのさまざまな機能が含まれています。ここでは、基本的な乱数生成から、高度な乱数生成までを紹介します。

基本的な乱数生成

C++11以降、乱数生成には <random> ライブラリが使用されます。このライブラリは、乱数エンジンと分布クラスを提供しています。以下に、基本的な整数乱数の生成例を示します。

#include <iostream>
#include <random>

int main() {
    std::random_device rd;  // ハードウェア乱数生成器を初期化
    std::mt19937 gen(rd()); // メルセンヌ・ツイスタの32ビット版を初期化
    std::uniform_int_distribution<> distrib(1, 100); // 1から100までの均等分布

    for (int i = 0; i < 10; ++i) {
        std::cout << distrib(gen) << " ";
    }

    return 0;
}

浮動小数点乱数の生成

浮動小数点数の乱数生成も可能です。以下の例では、0.0から1.0の間の浮動小数点乱数を生成します。

#include <iostream>
#include <random>

int main() {
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_real_distribution<> distrib(0.0, 1.0);

    for (int i = 0; i < 10; ++i) {
        std::cout << distrib(gen) << " ";
    }

    return 0;
}

正規分布による乱数生成

正規分布(ガウス分布)による乱数生成も標準ライブラリでサポートされています。以下に、平均0、標準偏差1の正規分布に従う乱数を生成する例を示します。

#include <iostream>
#include <random>

int main() {
    std::random_device rd;
    std::mt19937 gen(rd());
    std::normal_distribution<> distrib(0.0, 1.0);

    for (int i = 0; i < 10; ++i) {
        std::cout << distrib(gen) << " ";
    }

    return 0;
}

乱数シードの重要性

乱数生成のシード値は、生成される乱数列に大きな影響を与えます。同じシードを使うと同じ乱数列が生成されるため、再現性が必要なシナリオで役立ちます。

#include <iostream>
#include <random>

int main() {
    std::mt19937 gen(12345); // 固定シードを使用
    std::uniform_int_distribution<> distrib(1, 100);

    for (int i = 0; i < 10; ++i) {
        std::cout << distrib(gen) << " ";
    }

    return 0;
}

これらの方法を使うことで、さまざまな用途に対応した乱数を生成することができます。

複素数演算

C++の標準ライブラリには、複素数を扱うための<complex>ライブラリが含まれています。このライブラリを使用すると、複素数の演算を簡単に実装することができます。複素数は、実部と虚部を持つ数値であり、科学技術計算や工学の分野で広く使用されます。

複素数の基本

複素数は、std::complexクラスを使って定義します。以下の例では、複素数の基本的な操作を示します。

#include <iostream>
#include <complex>

int main() {
    std::complex<double> num1(1.0, 2.0); // 実部1.0、虚部2.0の複素数
    std::complex<double> num2(3.0, 4.0);

    std::cout << "num1: " << num1 << std::endl;
    std::cout << "num2: " << num2 << std::endl;

    return 0;
}

複素数の演算

複素数の加算、減算、乗算、除算は、通常の演算子(+, -, *, /)を使って行います。

#include <iostream>
#include <complex>

int main() {
    std::complex<double> num1(1.0, 2.0);
    std::complex<double> num2(3.0, 4.0);

    std::complex<double> sum = num1 + num2;
    std::complex<double> difference = num1 - num2;
    std::complex<double> product = num1 * num2;
    std::complex<double> quotient = num1 / num2;

    std::cout << "Sum: " << sum << std::endl;
    std::cout << "Difference: " << difference << std::endl;
    std::cout << "Product: " << product << std::endl;
    std::cout << "Quotient: " << quotient << std::endl;

    return 0;
}

複素数の絶対値と偏角

複素数の絶対値(大きさ)と偏角(位相)は、それぞれstd::absstd::arg関数を使って求めます。

#include <iostream>
#include <complex>

int main() {
    std::complex<double> num(1.0, 2.0);

    double magnitude = std::abs(num);
    double phase = std::arg(num);

    std::cout << "Magnitude: " << magnitude << std::endl;
    std::cout << "Phase: " << phase << std::endl;

    return 0;
}

複素数の共役

複素数の共役(虚部の符号を反転させたもの)は、std::conj関数を使って求めます。

#include <iostream>
#include <complex>

int main() {
    std::complex<double> num(1.0, 2.0);
    std::complex<double> conjugate = std::conj(num);

    std::cout << "Conjugate: " << conjugate << std::endl;

    return 0;
}

これらの操作を通じて、複素数を用いた高度な数学的計算をC++で実装することができます。

線形代数の基本

C++の標準ライブラリには線形代数の基本的な操作をサポートする機能が豊富に揃っています。ここでは、ベクトルや行列の基本的な計算方法について説明します。線形代数は、物理シミュレーション、データ解析、機械学習など多くの分野で不可欠な技術です。

ベクトルの基本操作

ベクトルは、数値の配列として表現されます。C++では、std::vectorクラスを使ってベクトルを操作します。以下に、ベクトルの加算とスカラー乗算の例を示します。

#include <iostream>
#include <vector>

int main() {
    std::vector<double> vec1 = {1.0, 2.0, 3.0};
    std::vector<double> vec2 = {4.0, 5.0, 6.0};
    std::vector<double> result(3);

    // ベクトルの加算
    for (size_t i = 0; i < vec1.size(); ++i) {
        result[i] = vec1[i] + vec2[i];
    }

    std::cout << "Vector addition result: ";
    for (double val : result) {
        std::cout << val << " ";
    }
    std::cout << std::endl;

    // スカラー乗算
    double scalar = 2.0;
    for (size_t i = 0; i < vec1.size(); ++i) {
        result[i] = vec1[i] * scalar;
    }

    std::cout << "Scalar multiplication result: ";
    for (double val : result) {
        std::cout << val << " ";
    }
    std::cout << std::endl;

    return 0;
}

行列の基本操作

行列は、ベクトルの配列として表現されます。C++では、std::vectorをネストして行列を表現します。以下に、行列の加算と行列積の例を示します。

#include <iostream>
#include <vector>

int main() {
    std::vector<std::vector<double>> mat1 = {
        {1.0, 2.0},
        {3.0, 4.0}
    };
    std::vector<std::vector<double>> mat2 = {
        {5.0, 6.0},
        {7.0, 8.0}
    };
    std::vector<std::vector<double>> result(2, std::vector<double>(2));

    // 行列の加算
    for (size_t i = 0; i < mat1.size(); ++i) {
        for (size_t j = 0; j < mat1[0].size(); ++j) {
            result[i][j] = mat1[i][j] + mat2[i][j];
        }
    }

    std::cout << "Matrix addition result:\n";
    for (const auto& row : result) {
        for (double val : row) {
            std::cout << val << " ";
        }
        std::cout << std::endl;
    }

    // 行列積
    for (size_t i = 0; i < mat1.size(); ++i) {
        for (size_t j = 0; j < mat2[0].size(); ++j) {
            result[i][j] = 0;
            for (size_t k = 0; k < mat1[0].size(); ++k) {
                result[i][j] += mat1[i][k] * mat2[k][j];
            }
        }
    }

    std::cout << "Matrix multiplication result:\n";
    for (const auto& row : result) {
        for (double val : row) {
            std::cout << val << " ";
        }
        std::cout << std::endl;
    }

    return 0;
}

行列の転置

行列の転置は、行と列を入れ替える操作です。以下に、行列の転置の例を示します。

#include <iostream>
#include <vector>

int main() {
    std::vector<std::vector<double>> mat = {
        {1.0, 2.0, 3.0},
        {4.0, 5.0, 6.0}
    };
    std::vector<std::vector<double>> transpose(mat[0].size(), std::vector<double>(mat.size()));

    // 行列の転置
    for (size_t i = 0; i < mat.size(); ++i) {
        for (size_t j = 0; j < mat[0].size(); ++j) {
            transpose[j][i] = mat[i][j];
        }
    }

    std::cout << "Matrix transpose result:\n";
    for (const auto& row : transpose) {
        for (double val : row) {
            std::cout << val << " ";
        }
        std::cout << std::endl;
    }

    return 0;
}

これらの基本操作を理解することで、より複雑な線形代数の問題に取り組む準備が整います。

ベクトルと行列の計算

ベクトルと行列の計算は、線形代数の基本であり、多くの応用分野で重要な役割を果たします。ここでは、ベクトルと行列の計算方法を詳細に説明します。

ベクトルの内積と外積

ベクトルの内積は、2つのベクトルの要素ごとの積の総和です。外積は、3次元ベクトルに対してのみ定義され、もう1つのベクトルを生成します。

#include <iostream>
#include <vector>

int main() {
    std::vector<double> vec1 = {1.0, 2.0, 3.0};
    std::vector<double> vec2 = {4.0, 5.0, 6.0};

    // 内積
    double dot_product = 0.0;
    for (size_t i = 0; i < vec1.size(); ++i) {
        dot_product += vec1[i] * vec2[i];
    }
    std::cout << "Dot product: " << dot_product << std::endl;

    // 外積
    std::vector<double> cross_product(3);
    cross_product[0] = vec1[1] * vec2[2] - vec1[2] * vec2[1];
    cross_product[1] = vec1[2] * vec2[0] - vec1[0] * vec2[2];
    cross_product[2] = vec1[0] * vec2[1] - vec1[1] * vec2[0];

    std::cout << "Cross product: ";
    for (double val : cross_product) {
        std::cout << val << " ";
    }
    std::cout << std::endl;

    return 0;
}

行列の逆行列

行列の逆行列は、ある行列と掛け合わせると単位行列になる行列です。逆行列の計算は、主にdet(行列式)とinv(逆行列)の関数を使用します。

#include <iostream>
#include <vector>
#include <iomanip>

using Matrix = std::vector<std::vector<double>>;

double determinant(const Matrix& mat, size_t n) {
    double det = 0.0;
    if (n == 1) return mat[0][0];
    if (n == 2) return mat[0][0] * mat[1][1] - mat[0][1] * mat[1][0];

    Matrix submat(n, std::vector<double>(n));
    for (size_t x = 0; x < n; ++x) {
        size_t subi = 0;
        for (size_t i = 1; i < n; ++i) {
            size_t subj = 0;
            for (size_t j = 0; j < n; ++j) {
                if (j == x) continue;
                submat[subi][subj] = mat[i][j];
                ++subj;
            }
            ++subi;
        }
        det += (x % 2 == 0 ? 1 : -1) * mat[0][x] * determinant(submat, n - 1);
    }
    return det;
}

void adjoint(const Matrix& mat, Matrix& adj) {
    int N = mat.size();
    if (N == 1) {
        adj[0][0] = 1;
        return;
    }
    int sign = 1;
    Matrix temp(N, std::vector<double>(N));
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            int subi = 0;
            for (int x = 0; x < N; x++) {
                if (x == i) continue;
                int subj = 0;
                for (int y = 0; y < N; y++) {
                    if (y == j) continue;
                    temp[subi][subj] = mat[x][y];
                    subj++;
                }
                subi++;
            }
            sign = ((i + j) % 2 == 0) ? 1 : -1;
            adj[j][i] = (sign) * (determinant(temp, N - 1));
        }
    }
}

bool inverse(const Matrix& mat, Matrix& inv) {
    int N = mat.size();
    double det = determinant(mat, N);
    if (det == 0) {
        std::cout << "Singular matrix, can't find its inverse";
        return false;
    }
    Matrix adj(N, std::vector<double>(N));
    adjoint(mat, adj);
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            inv[i][j] = adj[i][j] / double(det);
        }
    }
    return true;
}

int main() {
    Matrix mat = {
        {5, -2, 2, 7},
        {1, 0, 0, 3},
        {-3, 1, 5, 0},
        {3, -1, -9, 4}
    };
    Matrix inv(4, std::vector<double>(4));
    if (inverse(mat, inv)) {
        std::cout << "Inverse matrix is: \n";
        for (const auto& row : inv) {
            for (double val : row) {
                std::cout << std::setw(10) << val << " ";
            }
            std::cout << std::endl;
        }
    }
    return 0;
}

行列の行基本変形

行列の行基本変形は、行列を別の形に変換するための操作で、特にガウス・ジョルダン法などで使用されます。以下の例では、行列の行交換、行の定数倍、行の加算を行います。

#include <iostream>
#include <vector>

using Matrix = std::vector<std::vector<double>>;

void swap_rows(Matrix& mat, int row1, int row2) {
    std::swap(mat[row1], mat[row2]);
}

void multiply_row(Matrix& mat, int row, double scalar) {
    for (auto& val : mat[row]) {
        val *= scalar;
    }
}

void add_multiple_of_row(Matrix& mat, int source_row, int target_row, double scalar) {
    for (size_t i = 0; i < mat[source_row].size(); ++i) {
        mat[target_row][i] += scalar * mat[source_row][i];
    }
}

int main() {
    Matrix mat = {
        {2, 1, -1, -4},
        {-3, -1, 2, -1},
        {-2, 1, 2, -3}
    };

    std::cout << "Original matrix:\n";
    for (const auto& row : mat) {
        for (double val : row) {
            std::cout << val << " ";
        }
        std::cout << std::endl;
    }

    // 行の交換
    swap_rows(mat, 0, 1);

    // 行の定数倍
    multiply_row(mat, 1, -1);

    // 行の加算
    add_multiple_of_row(mat, 1, 2, 2);

    std::cout << "\nTransformed matrix:\n";
    for (const auto& row : mat) {
        for (double val : row) {
            std::cout << val << " ";
        }
        std::cout << std::endl;
    }

    return 0;
}

これらの操作を理解することで、C++を用いた線形代数の計算がより効果的に行えるようになります。

応用例: 数値解析

数値解析は、数値的手法を用いて問題を解決する技術であり、科学技術計算や工学分野で広く利用されています。ここでは、C++の標準ライブラリを用いた数値解析の応用例を紹介します。

ニュートン法による方程式の解法

ニュートン法は、非線形方程式の解を数値的に求める手法の一つです。以下に、ニュートン法を用いて方程式の解を求める例を示します。

#include <iostream>
#include <cmath>

double f(double x) {
    return x * x - 2; // f(x) = x^2 - 2
}

double f_prime(double x) {
    return 2 * x; // f'(x) = 2x
}

double newton_method(double initial_guess, double tolerance, int max_iterations) {
    double x = initial_guess;
    for (int i = 0; i < max_iterations; ++i) {
        double fx = f(x);
        double fpx = f_prime(x);
        if (std::fabs(fx) < tolerance) {
            break;
        }
        x = x - fx / fpx;
    }
    return x;
}

int main() {
    double initial_guess = 1.0;
    double tolerance = 1e-7;
    int max_iterations = 1000;

    double root = newton_method(initial_guess, tolerance, max_iterations);
    std::cout << "Root: " << root << std::endl;

    return 0;
}

数値積分: 台形法

台形法は、数値積分の基本的な手法の一つです。以下に、台形法を用いて関数の定積分を計算する例を示します。

#include <iostream>
#include <cmath>

double f(double x) {
    return std::sin(x); // f(x) = sin(x)
}

double trapezoidal_rule(double a, double b, int n) {
    double h = (b - a) / n;
    double sum = 0.5 * (f(a) + f(b));
    for (int i = 1; i < n; ++i) {
        sum += f(a + i * h);
    }
    return sum * h;
}

int main() {
    double a = 0.0;
    double b = M_PI; // pi
    int n = 1000;

    double result = trapezoidal_rule(a, b, n);
    std::cout << "Integral: " << result << std::endl;

    return 0;
}

線形方程式の解法: ガウス消去法

ガウス消去法は、線形方程式系を解くための標準的な手法です。以下に、ガウス消去法を用いて線形方程式を解く例を示します。

#include <iostream>
#include <vector>

using Matrix = std::vector<std::vector<double>>;
using Vector = std::vector<double>;

Vector gaussian_elimination(Matrix mat, Vector b) {
    int n = mat.size();

    // 前進消去
    for (int i = 0; i < n; ++i) {
        for (int j = i + 1; j < n; ++j) {
            double factor = mat[j][i] / mat[i][i];
            for (int k = i; k < n; ++k) {
                mat[j][k] -= factor * mat[i][k];
            }
            b[j] -= factor * b[i];
        }
    }

    // 後退代入
    Vector x(n);
    for (int i = n - 1; i >= 0; --i) {
        x[i] = b[i];
        for (int j = i + 1; j < n; ++j) {
            x[i] -= mat[i][j] * x[j];
        }
        x[i] /= mat[i][i];
    }

    return x;
}

int main() {
    Matrix mat = {
        {2, -1, 1},
        {3, 3, 9},
        {3, 3, 5}
    };
    Vector b = {2, 0, -1};

    Vector result = gaussian_elimination(mat, b);
    std::cout << "Solution: ";
    for (double val : result) {
        std::cout << val << " ";
    }
    std::cout << std::endl;

    return 0;
}

これらの数値解析手法を活用することで、C++を用いた高度な計算が可能になります。

演習問題

C++の標準ライブラリを使用した数値演算について理解を深めるために、以下の演習問題に取り組んでください。これらの問題を解くことで、実際のコーディングスキルを向上させることができます。

演習問題1: 基本的な数値演算

以下のコードを完成させて、2つの数値の加算、減算、乗算、除算を行い、それぞれの結果を出力するプログラムを作成してください。

#include <iostream>

int main() {
    double a = 8.0;
    double b = 4.0;

    double sum = // ここに加算のコードを記述
    double difference = // ここに減算のコードを記述
    double product = // ここに乗算のコードを記述
    double quotient = // ここに除算のコードを記述

    std::cout << "Sum: " << sum << std::endl;
    std::cout << "Difference: " << difference << std::endl;
    std::cout << "Product: " << product << std::endl;
    std::cout << "Quotient: " << quotient << std::endl;

    return 0;
}

演習問題2: 浮動小数点演算の精度

浮動小数点数の精度を確認するために、以下のプログラムを完成させてください。このプログラムでは、異なる精度の浮動小数点数を使用して円周率を表示します。

#include <iostream>
#include <iomanip>

int main() {
    float pi_f = 3.14159265358979323846f;
    double pi_d = 3.14159265358979323846;
    long double pi_ld = 3.14159265358979323846L;

    std::cout << std::setprecision(20);
    std::cout << "float: " << pi_f << std::endl;
    std::cout << "double: " << pi_d << std::endl;
    std::cout << "long double: " << pi_ld << std::endl;

    return 0;
}

演習問題3: 乱数生成

乱数を生成し、1から100までの範囲の乱数を10個表示するプログラムを完成させてください。

#include <iostream>
#include <random>

int main() {
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<> distrib(1, 100);

    for (int i = 0; i < 10; ++i) {
        std::cout << // ここに乱数生成のコードを記述
    }

    return 0;
}

演習問題4: 行列の計算

2×2の行列の加算を行うプログラムを完成させてください。

#include <iostream>
#include <vector>

int main() {
    std::vector<std::vector<int>> mat1 = {
        {1, 2},
        {3, 4}
    };
    std::vector<std::vector<int>> mat2 = {
        {5, 6},
        {7, 8}
    };
    std::vector<std::vector<int>> result(2, std::vector<int>(2));

    // 行列の加算
    for (int i = 0; i < 2; ++i) {
        for (int j = 0; j < 2; ++j) {
            result[i][j] = // ここに加算のコードを記述
        }
    }

    std::cout << "Matrix addition result:\n";
    for (const auto& row : result) {
        for (int val : row) {
            std::cout << val << " ";
        }
        std::cout << std::endl;
    }

    return 0;
}

演習問題5: 複素数演算

複素数の加算を行うプログラムを完成させてください。

#include <iostream>
#include <complex>

int main() {
    std::complex<double> num1(1.0, 2.0);
    std::complex<double> num2(3.0, 4.0);

    std::complex<double> sum = // ここに加算のコードを記述

    std::cout << "Sum: " << sum << std::endl;

    return 0;
}

これらの演習問題を解くことで、C++の標準ライブラリを用いた数値演算の理解を深めることができます。

まとめ

C++の標準ライブラリを用いた数値演算は、多様な数値操作を効率的に実現するための強力なツールです。本記事では、基本的な算術演算から浮動小数点演算、数学関数、乱数生成、複素数演算、線形代数、数値解析まで幅広くカバーしました。

これらの技術を習得することで、科学技術計算、データ解析、シミュレーションなど、さまざまな応用分野で役立つプログラムを開発することができます。また、演習問題を通じて実践的なスキルを身につけることができました。今後も、さらに高度な数値計算手法を学び、C++を用いた問題解決能力を高めていきましょう。

コメント

コメントする

目次