数学関数
計算用の便利な関数
C言語では言語の機能として足し算や引き算、余りなどを求めることができます。
それ以外にも算術用の便利な関数が用意されているので、よく使うものをいくつか紹介します。
なお、ほとんどの数学関数は#include <math.h>
を先頭に記述する必要があります。
VisualStudio以外のコンパイラを使用している場合でmath.h内の関数の実行に失敗する場合は、コンパイルオプションに「-lm」の指定が必要かもしれません。
gcc test.c -o test -lm
円周率
最初に、関数ではありませんがC言語での円周率について説明しておきます。
C言語では円周率の値は標準では定義されていません。
なので、自分で値を調べて#define
等で定数にしておくのが最も確実な方法です。
#define PI 3.14159265358979323846
いくつかのコンパイラでは円周率の値がmath.h
ヘッダー内に定数で定義されているので、それを使用します。
//gccの場合
#include <stdio.h>
#include <math.h>
int main()
{
//M_PIが円周率を表す定数
printf("%f\n", M_PI);
}
VisualStudioではmath.h
をインクルードした上で#define _USE_MATH_DEFINES
をコード先頭に追加することで、円周率を表す定数M_PI
が使用できます。
//VC++の場合
#define _USE_MATH_DEFINES
#include <stdio.h>
#include <math.h>
int main()
{
//M_PIが円周率を表す定数
printf("%f\n", M_PI);
}
floor、ceil、round関数
小数点以下の値を除去するにはfloor
関数、ceil
関数、round
関数を使用します。
- floor
- 小数点以下切り捨て
- ceil
- 小数点以下切り上げ
- round
- 小数点以下四捨五入
#include <stdio.h>
#include <math.h>
int main()
{
double d1 = 2.53;
double d2 = -8.361;
//戻り値はdouble型であることに注意
//切り捨て
printf("floor(%f)\n=%f\n", d1, floor(d1)); //2.000000
printf("floor(%f)\n=%f\n", d2, floor(d2)); //-9.000000
printf("\n");
//切り上げ
printf("ceil(%f)\n=%f\n", d1, ceil(d1)); //3.000000
printf("ceil(%f)\n=%f\n", d2, ceil(d2)); //-8.000000
printf("\n");
//四捨五入
printf("round(%f)\n=%f\n", d1, round(d1)); //3.000000
printf("round(%f)\n=%f\n", d2, round(d2)); //-8.000000
getchar();
}
floor(2.530000) =2.000000 floor(-8.361000) =-9.000000 ceil(2.530000) =3.000000 ceil(-8.361000) =-8.000000 round(2.530000) =3.000000 round(-8.361000) =-8.000000
戻り値はdouble型なので、必要に応じてint型などにキャストします。
これらの関数にはfloat型版のfloorf
関数、ceilf
関数、roundf
関数、long double型版のfloorl
関数、ceill
関数、roundl
関数が存在します。
戻り値もそれぞれの型になります。
float f = floorf(1.23f);
long double ld = floorl(1.23);
なお、古いコンパイラではround
関数は使えない場合があります。
その場合には0.5を足してからfloor
関数で切り捨てるなどの工夫が必要です。
double MyRound(double x)
{
if (x > 0.0)
return floor(x + 0.5);
else
return ceil(x - 0.5);
}
abs関数
abs
関数は値の絶対値を求めます。
絶対値とは符号を無視した値のことで、要するにマイナスを取り去る関数です。
int num1 = 5;
int num2 = -3;
printf("abs(%d)\n=%d\n", num1, abs(num1)); //5
printf("abs(%d)\n=%d\n", num2, abs(num2)); //3
abs(5) =5 abs(-3) =3
abs
関数の引数はint型です。
他の整数型は、long型はlabs
関数、long long型はllabs
関数が使用できます。
小数型は、float型はfabsf
関数、double型はfabs
関数、long dobule型はfabsl
関数がそれぞれ使用できます。
使い方は同じなのでコードは省略します。
整数型の関数に関してはコードの先頭に#include <stdlib.h>
が必要です。
pow、sqrt関数
pow
関数はxのy乗を返します。
sqrt
関数はxの平方根を返します。
double num1 = 5;
double num2 = 3;
printf("pow(%.0f, %.0f)\n=%f\n", num1, num2,
pow(num1, num2)); //125.000000
printf("sqrt(%.0f)\n=%f\n", num2,
sqrt(num2)); //1.732051
pow(5, 3) =125.000000 sqrt(3) =1.732051
これらの関数はdouble型を引数に取り、double型を返します。
int型を引数に指定しても暗黙の型変換でdouble型として処理されます。
pow関数のfloat型版はpowf
関数、long double型版はpowl
関数です。
sqrt関数のfloat型版はsqrtf
関数、long double型版はsqrtl
関数です。
なお、上のサンプルコードのsqrt
関数の実行結果は表示桁数の問題で丸められています。
(本当は「1.7320508...」)
sin、cos、tan関数
sin
関数は値のサインを返します。
cos
関数は値のコサインを返します。
tan
関数は値のタンジェントを返します。
これらは三角関数です。
引数にラジアンを指定し、それぞれ正弦、余弦、接弦を返します。
ラジアンとは、円の半径と等しい長さの円周で円を切り分けた時の角度を1とする値です。
これは一般にはあまりなじみがないですが、弧度法いう角度を表す方法のひとつです。
(小中学校あたりで習った角度を表す数値は度数法といいます)
度数法の値からラジアン値は「角度 × (円周率 ÷ 180)」で得ることができます。
#define M_PI 3.14159265358979323846
double radian = 60 * M_PI / 180.0;
printf("sin(%f)\n=%f\n", radian, sin(radian)); //0.866025
printf("cos(%f)\n=%f\n", radian, cos(radian)); //0.500000
printf("tan(%f)\n=%f\n", radian, tan(radian)); //1.732051
sin(1.047198) =0.866025 cos(1.047198) =0.500000 tan(1.047198) =1.732051
sin
関数のfloat型版はsinf
関数、long double型版はsinl
関数です。
cos
関数のfloat型版はcosf
関数、long double型版はcosl
関数です。
tan
関数のfloat型版はtanf
関数、long double型版はtanl
関数です。
asin、acos、atan関数
asin
関数は値のアークサインを返します。
acos
関数は値のアークコサインを返します。
atan
関数は値のアークタンジェントを返します。
これらは三角関数の逆関数です。
逆関数とはある関数の逆の働きをする関数のことで、元の関数で得られた値を逆関数に指定するとそのまま元の値を得ることができます。
#define M_PI 3.14159265358979323846
//元の角度
double degree = 60;
double radian = degree * M_PI / 180.0;
double dSin = sin(radian);
double dCos = cos(radian);
double dTan = tan(radian);
printf("asin(%f)\n=%f\n", dSin, asin(dSin)); //1.047198
printf("acos(%f)\n=%f\n", dCos, acos(dCos)); //1.047198
printf("atan(%f)\n=%f\n", dTan, atan(dTan)); //1.047198
printf("\n元の角度:%.0f\n", asin(dSin) / (M_PI / 180));
asin(0.866025) =1.047198 acos(0.500000) =1.047198 atan(1.732051) =1.047198 元の角度:60
asin
関数のfloat型版はasinf
関数、long double型版はasinl
関数です。
acos
関数のfloat型版はacosf
関数、long double型版はacosl
関数です。
atan
関数のfloat型版はatanf
関数、long double型版はatanl
関数です。
log、log10、exp関数
log
関数はxのe(ネイピア数)を底とする対数を返します。
log10
関数はxの10を底とする対数を返します。
exp
関数はeのx乗を返します。
double x = 2.5;
printf("log(%.1f)\n=%f\n", x, log(x)); //0.916291
printf("log10(%.1f)\n=%f\n", x, log10(x)); //0.397940
printf("exp(%.1f)\n=%f\n", x, exp(x)); //12.182494
log(2.5) =0.916291 log10(2.5) =0.397940 exp(2.5) =12.182494