数学関数

計算用の便利な関数

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