コンテンツにスキップ

C++/標準ライブラリ/cmath

出典: フリー教科書『ウィキブックス(Wikibooks)』

概要[編集]

cmathヘッダーの概要と役割の説明[編集]

C++のcmathヘッダーは、数学関数を提供するヘッダーファイルです。三角関数、双曲線関数、指数対数関数、その他の基本的な数学関数が用意されています。また、よく使われる数学定数も定義されています。これらの関数や定数を使うことで、C++プログラムで数学的な計算を行うことができます。

三角関数[編集]

std::sin(), std::cos(), std::tan()[編集]

std::sin()std::cos()std::tan()は、それぞれ三角関数の正弦、余弦、正接を計算する関数です。引数には角度(ラジアン)を指定します。

#include <cmath>
#include <iostream>

auto main() -> int {
    double angle = 0.5235987; // 30度に相当する角度
    std::cout << "std::sin(" << angle << ") = " << std::sin(angle) << std::endl; // 出力: 0.5
    std::cout << "std::cos(" << angle << ") = " << std::cos(angle) << std::endl; // 出力: 0.866025
    std::cout << "std::tan(" << angle << ") = " << std::tan(angle) << std::endl; // 出力: 0.577350
    return 0;
}

std::asin(), std::acos(), std::atan(), std::atan2()[編集]

std::asin()std::acos()std::atan()はそれぞれ、逆正弦、逆余弦、逆正接を計算する関数です。引数には-1から1の範囲の値を指定します。std::atan2()は、2つの引数yxを取り、y/xの逆正接を計算します。

#include <cmath>
#include <iostream>

auto main() -> int {
    double x = 0.5;
    std::cout << "std::asin(" << x << ") = " << std::asin(x) << std::endl; // 出力: 0.523599 (約30度)
    std::cout << "std::acos(" << x << ") = " << std::acos(x) << std::endl; // 出力: 1.04720 (約60度)
    std::cout << "std::atan(" << x << ") = " << std::atan(x) << std::endl; // 出力: 0.463648 (約26.57度)
    std::cout << "std::atan2(0.5, 1.0) = " << std::atan2(0.5, 1.0) << std::endl; // 出力: 0.463648 (約26.57度)
    return 0;
}

双曲線関数[編集]

std::sinh(), std::cosh(), std::tanh()[編集]

std::sinh()std::cosh()std::tanh()はそれぞれ、双曲線正弦、双曲線余弦、双曲線正接を計算する関数です。引数には実数値を指定します。

#include <cmath>
#include <iostream>

auto main() -> int {
    double x = 1.0;
    std::cout << "std::sinh(" << x << ") = " << std::sinh(x) << std::endl; // 出力: 1.17520
    std::cout << "std::cosh(" << x << ") = " << std::cosh(x) << std::endl; // 出力: 1.54308
    std::cout << "std::tanh(" << x << ") = " << std::tanh(x) << std::endl; // 出力: 0.761594
    return 0;
}

std::asinh(), std::acosh(), std::atanh()[編集]

std::asinh()std::acosh()std::atanh()はそれぞれ、逆双曲線正弦、逆双曲線余弦、逆双曲線正接を計算する関数です。

#include <cmath>
#include <iostream>

auto main() -> int {
    double x = 1.0;
    std::cout << "std::asinh(" << x << ") = " << std::asinh(x) << std::endl; // 出力: 0.881374
    std::cout << "std::acosh(" << x << ") = " << std::acosh(x) << std::endl; // 出力: 0 (不正な引数)
    std::cout << "std::atanh(" << x << ") = " << std::atanh(x) << std::endl; // 出力: inf (無限大)
    return 0;
}

std::acosh()std::atanh()の引数には制限があり、std::acosh()は1以上、std::atanh()は-1から1までの値でなければなりません。

指数関数と対数関数[編集]

std::exp(), std::log(), std::log10()[編集]

std::exp()は指数関数eのx乗を計算します。std::log()は自然対数を、std::log10()は常用対数を計算します。

#include <cmath>
#include <iostream>

auto main() -> int {
    double x = 1.0;
    std::cout << "std::exp(" << x << ") = " << std::exp(x) << std::endl; // 出力: 2.71828 (約e)
    std::cout << "std::log(" << x << ") = " << std::log(x) << std::endl; // 出力: 0 (std::log(1) = 0)
    std::cout << "std::log10(" << x << ") = " << std::log10(x) << std::endl; // 出力: 0
    return 0;
}

std::pow()[編集]

std::pow()は累乗を計算する関数です。2つの引数を取り、std::pow(x, y)と指定するとxy乗を計算します。

#include <cmath>
#include <iostream>

auto main() -> int {
    double x = 2.0, y = 3.0;
    std::cout << x << " ^ " << y << " = " << std::pow(x, y) << std::endl; // 出力: 8
    return 0;
}

最大値・最小値・絶対値[編集]

std::fmax(), std::fmin(), std::fdim()[編集]

std::fmax()std::fmin()はそれぞれ、2つの引数の大きい方、小さい方の値を返します。std::fdim()は、x - yの差の絶対値を返しますが、x > yの場合のみ計算され、x <= yの場合は0を返します。

#include <cmath>
#include <iostream>

auto main() -> int {
    double x = 3.0, y = 5.0;
    std::cout << "std::fmax(" << x << ", " << y << ") = " << std::fmax(x, y) << std::endl; // 出力: 5
    std::cout << "std::fmin(" << x << ", " << y << ") = " << std::fmin(x, y) << std::endl; // 出力: 3
    std::cout << "std::fdim(" << x << ", " << y << ") = " << std::fdim(x, y) << std::endl; // 出力: 0
    std::cout << "std::fdim(" << y << ", " << x << ") = " << std::fdim(y, x) << std::endl; // 出力: 2
    return 0;
}

続けて残りの項目を解説します。

std::fabs(), std::abs()[編集]

std::fabs()は引数の絶対値(実数値)を返し、std::abs()は引数の絶対値(整数値)を返します。

#include <cmath>
#include <iostream>

auto main() -> int {
    double x = -3.5;
    int y = -10;
    std::cout << "std::fabs(" << x << ") = " << std::fabs(x) << std::endl; // 出力: 3.5
    std::cout << "std::abs(" << y << ") = " << std::abs(y) << std::endl; // 出力: 10
    return 0;
}

切り上げ・切り捨て・残余[編集]

std::ceil(), std::floor(), std::trunc()[編集]

std::ceil()は引数以上の最小の整数値を返し、std::floor()は引数以下の最大の整数値を返し、std::trunc()は引数の整数部分を返します。

#include <cmath>
#include <iostream>

auto main() -> int {
    double x = 3.7, y = -3.2;
    std::cout << "std::ceil(" << x << ") = " << std::ceil(x) << std::endl; // 出力: 4
    std::cout << "std::floor(" << x << ") = " << std::floor(x) << std::endl; // 出力: 3
    std::cout << "std::trunc(" << x << ") = " << std::trunc(x) << std::endl; // 出力: 3
    std::cout << "std::ceil(" << y << ") = " << std::ceil(y) << std::endl; // 出力: -3
    std::cout << "std::floor(" << y << ") = " << std::floor(y) << std::endl; // 出力: -4
    std::cout << "std::trunc(" << y << ") = " << std::trunc(y) << std::endl; // 出力: -3
    return 0;
}

std::fmod(), std::remainder()[編集]

std::fmod()xyで割った余りを返し、std::remainder()xyで割った剰余を返します。

#include <cmath>
#include <iostream>

auto main() -> int {
    double x = 5.0, y = 2.0;
    std::cout << "std::fmod(" << x << ", " << y << ") = " << std::fmod(x, y) << std::endl; // 出力: 1
    std::cout << "std::remainder(" << x << ", " << y << ") = " << std::remainder(x, y) << std::endl; // 出力: 1
    return 0;
}

その他の数学関数[編集]

std::sqrt(), std::cbrt()[編集]

std::sqrt()は引数の正の平方根を返し、std::cbrt()は引数の立方根を返します。

#include <cmath>
#include <iostream>

auto main() -> int {
    double x = 16.0, y = 27.0;
    std::cout << "std::sqrt(" << x << ") = " << std::sqrt(x) << std::endl; // 出力: 4
    std::cout << "std::cbrt(" << y << ") = " << std::cbrt(y) << std::endl; // 出力: 3
    return 0;
}

std::hypot()[編集]

std::hypot()は、2つの直交する実数値の三平方の和の平方根(ユークリッド距離)を計算します。

#include <cmath>
#include <iostream>

auto main() -> int {
    double x = 3.0, y = 4.0;
    std::cout << "std::hypot(" << x << ", " << y << ") = " << std::hypot(x, y) << std::endl; // 出力: 5 (std::sqrt(3^2 + 4^2))
    return 0;
}

std::fma()[編集]

std::fma()は、3つの引数xyzに対して、(x * y) + zの値を精度を失うことなく計算します。

#include <cmath>
#include <iostream>

auto main() -> int {
    double x = 1e20, y = 1e-7, z = 3.0;
    double result = x * y + z;
    std::cout << "Naive: " << x << " * " << y << " + " << z << " = " << result << std::endl; // 出力: 3
    result = std::fma(x, y, z);
    std::cout << "Using fma: " << x << " * " << y << " + " << z << " = " << result << std::endl; // 出力: 10000003
    return 0;
}

例外処理[編集]

C++11以降では、cmathヘッダーの関数からstd::domain_errorやstd::range_errorといった例外が送出(throw)される可能性があります。

std::domain_error[編集]

引数がその関数のドメインの外にある場合にthrowされる可能性があります。具体的には以下のようなケースです。

  • log()やlog10()への0以下の値の渡し
  • acos()への絶対値1を超える値の渡し
  • acosh()への1未満の値の渡し
  • atanh()への絶対値1を超える値の渡し

std::range_error[編集]

関数の結果が表現可能な値の範囲を超えた場合にthrowされる可能性があります。例えばexp()への大きすぎる値の渡しなどです。

#include <cmath>
#include <iostream>
#include <limits>

auto main() -> int {
    double x = std::numeric_limits<double>::max();
    try {
        double result = std::exp(x);
        std::cout << "std::exp(" << x << ") = " << result << std::endl; 
    } catch(const std::range_error& E) {
        std::cout << "std::exp(" << x << "): " << E.what() << std::endl;
        // -> std::exp(1.79769e+308) = inf
    }

    return 0;
}

これらの例外は実装依存であり、必ずしもthrowされるわけではありません。しかし、C++11以降ではこれらの例外を使ってエラー処理を行うことが推奨されています。

定数[編集]

M_E, M_LOG2E, M_LOG10E, M_LN2, M_LN10, M_PI, M_PI_2, M_PI_4, M_1_PI, M_2_PI, M_2_SQRTPI, M_SQRT2, M_SQRT1_2[編集]

cmathヘッダーには、よく使われる数学定数がマクロとして定義されています。

  • M_E: 自然対数の底e (約2.71828)
  • M_LOG2E:std::log2(e) (約1.44270)
  • M_LOG10E:std::log10(e) (約0.434294)
  • M_LN2:std::ln(2) (約0.693147)
  • M_LN10:std::ln(10) (約2.30259)
  • M_PI: 円周率π (約3.14159)
  • M_PI_2: π/2 (約1.57080)
  • M_PI_4: π/4 (約0.785398)
  • M_1_PI: 1/π (約0.318310)
  • M_2_PI: 2/π (約0.636620)
  • M_2_SQRTPI: 2/√π (約1.12838)
  • M_SQRT2: √2 (約1.41421)
  • M_SQRT1_2: 1/√2 (約0.707107)

これらの定数を使うことで、プログラムの可読性が高まり、計算ミスを防ぐこともできます。

まとめ[編集]

C++のcmathヘッダーには、三角関数、双曲線関数、指数対数関数、その他の基本的な数学関数が用意されています。これらの関数を使うことで、プログラムで数学的な計算を行うことができます。また、よく使われる定数も定義されているので、プログラムの可読性が高まります。cmathヘッダーを適切に使いこなすことで、数値計算を扱うC++プログラムの開発が容易になります。