double 是 float 的“加强版”或“高精度版”,它们都是用来表示带小数点的浮点数,但在精度和内存占用上有根本性的区别。

(图片来源网络,侵删)
核心区别总结表
| 特性 | float (单精度浮点数) |
double (双精度浮点数) |
|---|---|---|
| 关键字 | float |
double |
| 内存占用 | 4 字节 (32位) | 8 字节 (64位) |
| 有效数字 | 约 6-7 位十进制数 | 约 15-16 位十进制数 |
| 表示范围 | 较小 | 更大 |
| 运算速度 | 一般更快 | 一般稍慢 |
| 默认类型 | 在C语言中,14 这样的字面量默认是 double |
在C语言中,14 这样的字面量默认是 double |
| 后缀 | 可选 f 或 F (如 14f) |
可选 l 或 L (如 14L) |
内存占用
这是最根本的区别,直接决定了其他所有特性。
float: 占用 4 个字节(32位),这 32 位被划分为三部分:符号位、指数位和尾数位。double: 占用 8 个字节(64位),这 64 位同样被划分为三部分,但每个部分的位数都比float多。
为什么叫“单精度”和“双精度”? 因为
double的位数(64位)是float(32位)的两倍,所以它的精度和表示范围都“翻倍”了,因此被称为“双精度”。
精度
精度指的是一个浮点数能够表示的有效数字的位数,这是 float 和 double 最重要的区别。
float: 大约能提供 6 到 7 位有效数字。double: 大约能提供 15 到 16 位有效数字。
什么是“有效数字”? 有效数字是指一个数中从第一个非零数字开始,到最后一个数字为止的所有数字。

(图片来源网络,侵删)
代码示例:精度对比
#include <stdio.h>
int main() {
float f_num = 123.456789012345f; // 注意 f 后缀,表示这是一个 float
double d_num = 123.456789012345; // 默认是 double
printf("Float value: %.10f\n", f_num); // 打印 float,保留10位小数
printf("Double value: %.10f\n", d_num); // 打印 double,保留10位小数
// 另一个例子
float f_pi = 3.14159265358979323846f;
double d_pi = 3.14159265358979323846;
printf("Float pi: %.15f\n", f_pi);
printf("Double pi: %.15f\n", d_pi);
return 0;
}
可能的输出结果:
Float value: 123.4567871094 // 注意,从第8位开始就出现误差了
Double value: 123.4567890123 // 保持了更高的精度
Float pi: 3.141592741012573 // 只保留了约7位有效数字,后续是无效的
Double pi: 3.141592653589793 // 保持了约15位有效数字
从输出中可以清晰地看到,float 在存储超过其精度的数字时,会丢失精度,而 double 则能准确存储更多位数。
表示范围
虽然两者都能表示非常大和非常小的数,但由于 double 的指数部分位数更多,它的表示范围比 float 更大。
float的范围大约在±3.4E-38到±3.4E+38之间。double的范围大约在±1.7E-308到±1.7E+308之间。
在大多数日常应用中,两者的范围都足够了,但在科学计算(如天体物理、分子模拟)中,double 的巨大范围就显得至关重要。
默认类型和后缀
在C语言中,当你写一个带小数点的数字时,编译器默认将其视为 double 类型。
14是一个double类型。14f或14F是一个float类型,这里的f是一个后缀,告诉编译器:“请把这个数当作float来处理”。14l或14L是一个long double类型(精度比double还高)。
代码示例:默认类型
#include <stdio.h>
int main() {
float f;
double d;
// 3.14 默认是 double,需要将 double 赋值给 float
// 这是允许的,但可能会有精度损失(编译器可能会警告)
f = 3.14;
// 正确的做法是使用 f 后缀
f = 3.14f;
d = 3.14; // 直接赋值,类型匹配
printf("f = %f (size: %zu bytes)\n", f, sizeof(f));
printf("d = %f (size: %zu bytes)\n", d, sizeof(d));
return 0;
}
运算速度
在大多数现代计算机上,浮点运算是通过专门的硬件(FPU,浮点运算单元)来完成的。
float(32位) 的运算通常比double(64位) 稍快一些,因为数据总线传输和处理的数据量更小。double(64位) 是CPU和操作系统原生支持的“自然”精度,其运算速度已经非常快。- 除非你在进行性能极其敏感的科学计算或游戏开发(每秒数亿次运算),否则这个速度差异对你的程序影响微乎其微。为了代码的健壮性和正确性,优先使用
double是更好的选择。
何时使用 float,何时使用 double?
这是一个很好的实践问题。
优先使用 double 的情况(90% 的情况)
- 默认选择:如果你不确定,就用
double,它能提供更高的精度,避免很多难以发现的精度错误。 - 需要高精度的计算:如财务计算(虽然财务计算最好用整数或专门的十进制库)、物理模拟、工程计算等。
- 函数参数:标准库中所有处理浮点数的函数(如
sin,cos,sqrt,pow)都使用double作为参数和返回类型,使用double可以避免不必要的类型转换。
可以考虑使用 float 的情况
- 内存极度受限:当你需要存储数百万甚至更多的浮点数时(在3D图形学中处理顶点坐标,或某些嵌入式系统),使用
float可以节省一半的内存。 - 性能极其敏感:在图形渲染、游戏引擎等需要每秒进行海量浮点运算的场景,使用
float可能会带来微小的性能提升。 - 数据来源就是
float:从网络协议或某些传感器中读取的数据本身就是float类型,直接使用可以避免转换。
| 场景 | 推荐类型 | 理由 |
|---|---|---|
| 通用编程、科学计算、财务软件 | double |
高精度,是默认且最安全的选择 |
| 3D图形学、大规模数据集、嵌入式系统 | float |
节省内存,在特定场景下性能稍好 |
| 不确定 | double |
优先保证正确性和精度 |
记住这个黄金法则:在C语言中,除非你有充分的理由使用 float,否则请始终使用 double。
