C++/標準ライブラリ/cmath
概要
[編集]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つの引数yとxを取り、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)と指定するとxのy乗を計算します。
#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()はxをyで割った余りを返し、std::remainder()はxをyで割った剰余を返します。
#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つの引数x、y、zに対して、(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++プログラムの開発が容易になります。