math.h 是C语言标准库中的数学函数头文件,提供了一系列数学计算函数。使用前需要包含头文件:

1
#include <math.h>

注意:编译时需要链接数学库,例如在GCC中使用 -lm 选项:

1
gcc program.c -o program -lm

常用数学常数

预定义常数:

1
2
3
4
5
6
7
8
9
10
11
#include <stdio.h>
#include <math.h>
int main()
{
printf("圆周率 π = %.10f\n", M_PI); // 3.1415926536
printf("自然常数 e = %.10f\n", M_E); // 2.7182818285
printf("无穷大 INFINITY = %f\n", INFINITY);
printf("非数 NAN = %f\n", NAN);

return 0;
}

基本数学运算函数

绝对值函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>
#include <math.h>
#include <stdlib.h> // 注意:abs()在stdlib.h中
int main()
{
int x = -10;
double y = -3.14;
long z = -100L;

printf("abs(-10) = %d\n", abs(x)); // 整型绝对值,在stdlib.h
printf("fabs(-3.14) = %.2f\n", fabs(y)); // 浮点型绝对值
printf("labs(-100) = %ld\n", labs(z)); // 长整型绝对值,在stdlib.h

// C99新增;
printf("fabsf(-3.14f) = %.2f\n", fabsf(-3.14f)); // float版本
printf("fabsl(-3.14L) = %.2Lf\n", fabsl(-3.14L)); // long double版本

return 0;
}

取整函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdio.h>
#include <math.h>
int main()
{
double x = 3.7;
double y = -2.3;

printf("ceil(3.7) = %.1f\n", ceil(x)); // 向上取整:4.0
printf("ceil(-2.3) = %.1f\n", ceil(y)); // -2.0

printf("floor(3.7) = %.1f\n", floor(x)); // 向下取整:3.0
printf("floor(-2.3) = %.1f\n", floor(y)); // -3.0

printf("trunc(3.7) = %.1f\n", trunc(x)); // 向零取整:3.0
printf("trunc(-2.3) = %.1f\n", trunc(y)); // -2.0

printf("round(3.7) = %.1f\n", round(x)); // 四舍五入:4.0
printf("round(-2.3) = %.1f\n", round(y)); // -2.0

return 0;
}

余数函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
#include <math.h>

int main()
{
double x = 10.5;
double y = 3.2;

printf("fmod(10.5, 3.2) = %.2f\n", fmod(x, y)); // 浮点数取余
printf("remainder(10.5, 3.2) = %.2f\n", remainder(x, y)); // 标准余数

// C99新增:remquo函数,同时获取余数和商
int quo;
double rem = remquo(x, y, &quo);
printf("remquo(10.5, 3.2): 余数=%.2f, 商=%d\n", rem, quo);

return 0;
}

幂函数与对数函数

指数与对数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <stdio.h>
#include <math.h>

int main()
{
double x = 2.0;
double y = 8.0;

// 指数函数
printf("exp(2.0) = e^2 = %.4f\n", exp(x)); // e的x次幂
printf("exp2(3.0) = 2^3 = %.1f\n", exp2(3.0)); // 2的x次幂
printf("pow(2.0, 3.0) = %.1f\n", pow(2.0, 3.0)); // x的y次幂

// 对数函数
printf("log(7.389) = %.2f\n", log(7.389)); // 自然对数(以e为底)
printf("log10(100) = %.2f\n", log10(100.0)); // 常用对数(以10为底)
printf("log2(8) = %.2f\n", log2(8.0)); // 以2为底的对数

// 分解浮点数
int exponent;
double mantissa = frexp(12.5, &exponent);
printf("frexp(12.5): 尾数=%.2f, 指数=%d\n", mantissa, exponent);

return 0;
}

平方根与立方根

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
#include <math.h>

int main()
{
double x = 16.0;

printf("sqrt(16) = %.2f\n", sqrt(x)); // 平方根
printf("cbrt(27) = %.2f\n", cbrt(27.0)); // 立方根

// 勾股定理函数(C99)
printf("hypot(3, 4) = %.2f\n", hypot(3.0, 4.0)); // √(3²+4²)

return 0;
}

三角函数

基本三角函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <stdio.h>
#include <math.h>

int main()
{
double angle = 45.0; // 角度
double radian = angle * M_PI / 180.0; // 转换为弧度

printf("sin(45°) = %.4f\n", sin(radian));
printf("cos(45°) = %.4f\n", cos(radian));
printf("tan(45°) = %.4f\n", tan(radian));

// 反三角函数
double value = 0.7071;
printf("asin(0.7071) = %.2f°\n", asin(value) * 180 / M_PI);
printf("acos(0.7071) = %.2f°\n", acos(value) * 180 / M_PI);
printf("atan(1.0) = %.2f°\n", atan(1.0) * 180 / M_PI);

// atan2函数 - 计算y/x的反正切,可以正确处理象限
printf("atan2(1, 1) = %.2f°\n", atan2(1.0, 1.0) * 180 / M_PI);
printf("atan2(1, -1) = %.2f°\n", atan2(1.0, -1.0) * 180 / M_PI);

return 0;
}

双曲函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
#include <math.h>

int main()
{
double x = 1.0;

printf("sinh(1.0) = %.4f\n", sinh(x)); // 双曲正弦
printf("cosh(1.0) = %.4f\n", cosh(x)); // 双曲余弦
printf("tanh(1.0) = %.4f\n", tanh(x)); // 双曲正切

// 反双曲函数
printf("asinh(1.175) = %.4f\n", asinh(1.175));
printf("acosh(1.543) = %.4f\n", acosh(1.543));
printf("atanh(0.462) = %.4f\n", atanh(0.462));

return 0;
}

误差函数与伽玛函数(C99新增)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>
#include <math.h>
int main()
{
double x = 1.0;

// 误差函数
printf("erf(1.0) = %.6f\n", erf(x)); // 误差函数
printf("erfc(1.0) = %.6f\n", erfc(x)); // 互补误差函数

// 伽玛函数
printf("tgamma(5.0) = %.2f (4! = 24)\n", tgamma(5.0)); // 伽玛函数
printf("lgamma(5.0) = %.6f\n", lgamma(5.0)); // 伽玛函数的自然对数

return 0;
}

浮点数分类与操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <stdio.h>
#include <math.h>
#include <float.h>

int main()
{
double x = 1.0 / 0.0; // 无穷大
double y = 0.0 / 0.0; // 非数
double z = 3.14;

// 浮点数分类
printf("isinf(x) = %d\n", isinf(x)); // 是否无穷大
printf("isnan(y) = %d\n", isnan(y)); // 是否非数
printf("isfinite(z) = %d\n", isfinite(z)); // 是否有限数

// 符号操作
printf("copysign(3.14, -1) = %.2f\n", copysign(3.14, -1.0)); // 复制符号
printf("signbit(-3.14) = %d\n", signbit(-3.14)); // 获取符号位

// 最接近整数函数
printf("rint(2.3) = %.1f\n", rint(2.3)); // 当前舍入模式下的舍入值
printf("nearbyint(2.3) = %.1f\n", nearbyint(2.3));

return 0;
}

数值比较函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>
#include <math.h>
int main()
{
double x = 1.0;
double y = 1.0000000001;

// 浮点数比较(考虑误差)
printf("fmax(3.14, 2.71) = %.2f\n", fmax(3.14, 2.71)); // 最大值
printf("fmin(3.14, 2.71) = %.2f\n", fmin(3.14, 2.71)); // 最小值

// 带NaN处理的比较
printf("fmax(3.14, NAN) = %.2f\n", fmax(3.14, NAN)); // 返回非NaN值

// 差值函数
printf("fdim(5.0, 3.0) = %.2f\n", fdim(5.0, 3.0)); // 正差值(x-y如果x>y,否则0)

return 0;
}

实用示例

示例1:二次方程求解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdio.h>
#include <math.h>

void solve_quadratic(double a, double b, double c)
{
double discriminant = b * b - 4 * a * c;

if (discriminant > 0) {
double root1 = (-b + sqrt(discriminant)) / (2 * a);
double root2 = (-b - sqrt(discriminant)) / (2 * a);
printf("两个实根: %.2f, %.2f\n", root1, root2);
} else if (discriminant == 0) {
double root = -b / (2 * a);
printf("一个实根: %.2f\n", root);
} else {
double real = -b / (2 * a);
double imaginary = sqrt(-discriminant) / (2 * a);
printf("两个复根: %.2f + %.2fi, %.2f - %.2fi\n",
real, imaginary, real, imaginary);
}
}

示例2:计算圆的几何属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
#include <math.h>

void circle_properties(double radius)
{
double area = M_PI * pow(radius, 2);
double circumference = 2 * M_PI * radius;
double volume = (4.0/3.0) * M_PI * pow(radius, 3);

printf("半径: %.2f\n", radius);
printf("面积: %.2f\n", area);
printf("周长: %.2f\n", circumference);
printf("球体积: %.2f\n", volume);
}

示例3:统计计算

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <stdio.h>
#include <math.h>

void calculate_statistics(double data[], int n)
{
double sum = 0.0, mean, variance = 0.0, std_dev;

// 计算平均值
for (int i = 0; i < n; i++) {
sum += data[i];
}
mean = sum / n;

// 计算方差和标准差
for (int i = 0; i < n; i++) {
variance += pow(data[i] - mean, 2);
}
variance /= n;
std_dev = sqrt(variance);

printf("平均值: %.4f\n", mean);
printf("方差: %.4f\n", variance);
printf("标准差: %.4f\n", std_dev);
}

注意事项与最佳实践

错误处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdio.h>
#include <math.h>
#include <errno.h> // 错误处理

int main()
{
double result;
errno = 0; // 清除错误状态

result = sqrt(-1.0); // 无效输入

if (errno != 0) {
perror("sqrt函数错误");
}

if (isnan(result)) {
printf("结果不是数字\n");
}

return 0;
}

精度考虑

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>
#include <math.h>

int main()
{
// 浮点数精度问题
double a = 0.1;
double b = 0.2;
double c = 0.3;

printf("0.1 + 0.2 == 0.3? %s\n",
a + b == c ? "true" : "false"); // 可能输出false!

// 更好的比较方式(考虑浮点误差)
double epsilon = 1e-10;
printf("使用容差比较: %s\n",
fabs((a + b) - c) < epsilon ? "true" : "false");

return 0;
}