什么是浮点数?
浮点数就是用来表示小数(实数)的数据类型。让我用通俗易懂的方式解释:
什么是浮点数?
浮点数 = 科学计数法的二进制版本
就像我们写很大的数会用科学计数法:
- 1,200,000 = 1.2 × 10⁶
- 0.000012 = 1.2 × 10⁻⁵
计算机用类似的方法表示小数,但是使用二进制。
浮点数的组成
浮点数由三部分组成(以32位float为例):
[符号位] [指数部分] [小数部分]
1位 8位 23位举例: 数字 -13.625 在计算机中如何表示?
- 符号位:负号 → 1
转换为二进制:
- 整数部分:13 = 1101(二进制)
- 小数部分:0.625 = 0.101(二进制)
- 合并:13.625 = 1101.101(二进制)
科学计数法:1101.101 = 1.101101 × 2³
- 小数部分:1.101101 → 去掉前面的1,得到 101101
- 指数部分:3
为什么叫"浮点数"?
"浮点"的意思是小数点的位置可以浮动:
// 这些数都是浮点数,小数点位置不同
float a = 123.45; // 小数点在第3位后
float b = 1.2345; // 小数点在第1位后
float c = 12345.0; // 小数点在第5位后浮点数的实际问题
#include <stdio.h>
int main() {
// 问题1:有些十进制小数无法精确表示为二进制小数
float f = 0.1f; // 0.1在十进制中很简单,但在二进制中是无限循环的!
printf("0.1 的实际存储值: %.20f\n", f);
// 问题2:连续相加会产生误差
float sum = 0.0f;
for (int i = 0; i < 10; i++) {
sum += 0.1f;
}
printf("0.1相加10次: %.10f\n", sum); // 可能不是精确的1.0
return 0;
}生活中的类比
想象一把尺子:
- 整数:只能量整厘米(1cm, 2cm, 3cm...)
- 浮点数:可以量毫米(1.1cm, 1.2cm, 1.25cm...),但精度有限
关键点:
- 浮点数不是绝对精确的(就像尺子有最小刻度)
- 表示范围很大,可以表示非常小或非常大的数
- 运算可能产生微小误差
编程中的浮点数类型
#include <stdio.h>
#include <float.h>
int main() {
printf("float 精度: 约%d位有效数字\n", FLT_DIG);
printf("double 精度: 约%d位有效数字\n", DBL_DIG);
printf("float 范围: %e 到 %e\n", FLT_MIN, FLT_MAX);
printf("double 范围: %e 到 %e\n", DBL_MIN, DBL_MAX);
return 0;
}简单总结: 浮点数就是计算机用来表示小数的近似方法,虽然不完美,但足够应对大多数科学计算和工程应用的需求。
经典疑问
float 和 double 的区别
| 特性 | float | double |
|---|---|---|
| 大小 | 4字节 (32位) | 8字节 (64位) |
| 精度 | 约6-7位有效数字 | 约15-16位有效数字 |
| 范围 | ±3.4e-38 到 ±3.4e+38 | ±1.7e-308 到 ±1.7e+308 |
| 关键字 | float | double |
printf 中的格式说明符
#include <stdio.h>
int main() {
float f = 3.141592653589793f; // 注意后面的 f
double d = 3.141592653589793;
// 正确的格式说明符
printf("float: %f\n", f); // 默认显示6位小数
printf("double: %lf\n", d); // %lf 用于 double
// 控制小数位数
printf("float(2位): %.2f\n", f);
printf("double(4位): %.4lf\n", d);
// 科学计数法表示
printf("科学计数法: %e\n", f);
printf("科学计数法: %le\n", d);
return 0;
}浮点数的玄学问题
#include <stdio.h>
#include <math.h>
int main() {
// 问题1:精度损失
float a = 0.1f;
float b = 0.2f;
float c = a + b;
printf("0.1 + 0.2 = %.10f\n", c); // 可能不是精确的 0.3
// 问题2:比较浮点数不要直接用 ==
if (fabs(c - 0.3f) < 1e-6) { // 使用误差范围比较
printf("c ≈ 0.3\n");
}
// 问题3:大数吃小数
float big = 1e8f;
float small = 1.0f;
printf("大数 + 小数 = %f\n", big + small); // 可能还是 100000000
return 0;
}四舍五入的正确用法
#include <stdio.h>
#include <math.h>
int main() {
double numbers[] = {3.4, 3.5, 3.6, -2.3, -2.7};
int size = sizeof(numbers) / sizeof(numbers[0]);
printf("四舍五入示例:\n");
for (int i = 0; i < size; i++) {
printf("%.1f -> %.0f\n", numbers[i], round(numbers[i]));
}
// 其他相关的舍入函数
double x = 2.7;
printf("\n其他舍入函数:\n");
printf("round(%.1f) = %.0f (四舍五入)\n", x, round(x));
printf("ceil(%.1f) = %.0f (向上取整)\n", x, ceil(x));
printf("floor(%.1f) = %.0f (向下取整)\n", x, floor(x));
printf("trunc(%.1f) = %.0f (向零取整)\n", x, trunc(x));
return 0;
}
此处评论已关闭