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++プログラムの開発が容易になります。