数学関数

計算用の便利な関数

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型用とlong double型用も存在します。
float型用は関数名の末尾に「f」を、long double型用は末尾に「l」を付けます。
戻り値もそれぞれの型になります。

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

long型用にlabs関数、double型用にfabs関数もあります。
llabs(long long int型用)、fabsf(float型用)などもあります。
使い方は同じなのでコードは省略します。

もし使用できない場合は#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)
=123.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