double 是 C 语言中一种用于表示双精度浮点数的数据类型,与 int(整数)不同,double 用于存储带有小数部分的数字,14, -0.001, 022e23 (科学计数法)。
double 的基本概念
- 精度:
double通常占用 8 个字节(64位)的内存空间,它提供了比float(单精度,通常4字节)更高的精度,大约可以提供 15 到 17 位有效数字。 - 范围:
double的表示范围非常大,大约从±1.7E-308到±1.7E+308。 - 声明和初始化:
double pi = 3.141592653589793; double temperature = -10.5; double scientific = 6.022e23; // 等同于 6.022 * 10^23
double 的运算
double 主要支持以下几种运算:
a) 算术运算
这是最常见的运算,double 可以参与所有标准的算术运算。
| 运算符 | 名称 | 示例 | 结果 |
|---|---|---|---|
| 加法 | double a = 5.5; double b = 2.2; double c = a + b; |
c 的值为 7 |
|
| 减法 | double a = 5.5; double b = 2.2; double c = a - b; |
c 的值为 3 |
|
| 乘法 | double a = 2.0; double b = 3.5; double c = a * b; |
c 的值为 0 |
|
| 除法 | double a = 10.0; double b = 4.0; double c = a / b; |
c 的值为 5 |
|
| 取模 | 不适用 | 运算符只能用于整数类型(int, long 等),不能用于 double。 |
代码示例:
#include <stdio.h>
int main() {
double num1 = 10.5;
double num2 = 3.0;
double sum = num1 + num2;
double difference = num1 - num2;
double product = num1 * num2;
double quotient = num1 / num2;
printf("和: %.2f\n", sum); // 输出: 和: 13.50
printf("差: %.2f\n", difference); // 输出: 差: 7.50
printf("积: %.2f\n", product); // 输出: 积: 31.50
printf("商: %.2f\n", quotient); // 输出: 商: 3.50
return 0;
}
b) 关系运算
double 可以进行大小比较。
| 运算符 | 名称 | 示例 | 结果 |
|---|---|---|---|
> |
大于 | 14 > 2.71 |
结果为 1 (真) |
< |
小于 | 14 < 2.71 |
结果为 0 (假) |
>= |
大于等于 | 14 >= 3.14 |
结果为 1 (真) |
<= |
小于等于 | 14 <= 3.14 |
结果为 1 (真) |
| 等于 | 14 == 3.14 |
结果为 1 (真) |
|
| 不等于 | 14 != 2.71 |
结果为 1 (真) |
⚠️ 重要提示:浮点数比较的陷阱
由于计算机内部使用二进制存储浮点数,很多十进制小数在二进制中是无限循环小数,无法被精确表示,直接使用 比较两个 double 是否相等可能会得到错误的结果。
错误示例:
double a = 0.1 + 0.2;
if (a == 0.3) {
printf("相等\n"); // 这行代码可能不会执行!
} else {
printf("不相等\n"); // 这行代码更有可能执行
}
// 输出可能是 "不相等",因为 a 的实际值可能是 0.30000000000000004
正确的比较方法: 使用一个很小的“容差值”(epsilon)来判断两个浮点数是否“足够接近”。
#include <stdio.h>
#include <math.h> // 需要包含 math.h 来使用 fabs()
int main() {
double a = 0.1 + 0.2;
double b = 0.3;
double epsilon = 1e-9; // 定义一个很小的容差
if (fabs(a - b) < epsilon) {
printf("a 和 b 足够接近,可以认为是相等的,\n");
} else {
printf("a 和 b 不相等,\n");
}
return 0;
}
c) 赋值运算
除了基本的 ,还有复合赋值运算符。
| 运算符 | 等价于 | 示例 |
|---|---|---|
a = a + b |
a += b; |
|
a = a - b |
a -= b; |
|
a = a * b |
a *= b; |
|
a = a / b |
a /= b; |
代码示例:
double price = 99.99; double discount = 10.0; price -= discount; // price 现在是 89.99 price *= 1.08; // price 现在是 89.99 * 1.08 (加上8%的税)
double 与 int 的混合运算
当 double 和 int 进行混合运算时,C 语言的类型提升规则会自动将 int 转换为 double,整个运算在 double 精度下进行。
示例:
int i = 5; double d = 2.5; // 1. 混合运算 double result1 = i + d; // int 5 被临时提升为 double 5.0 // result1 的结果是 7.5 (double 类型) // 2. 混合赋值 double result2 = i / d; // int 5 被提升为 double 5.0 // result2 的结果是 2.0 (double 类型) // 3. 一个常见的陷阱 int a = 5; int b = 2; double result3 = a / b; // 注意:这里先进行 a / b 的整数除法 // a / b 的结果是 2 (int 类型),然后这个 int 2 被赋给 double result3 // result3 的最终值是 2.0,而不是期望的 2.5
如何避免陷阱? 如果希望得到浮点数结果,确保至少有一个操作数是浮点数。
// 正确做法:将其中一个操作数转换为 double double result4 = (double)a / b; // 先将 a 转换为 5.0,然后进行 5.0 / 2.0 // result4 的结果是 2.5 // 或者 double result5 = a / (double)b; // 先将 b 转换为 2.0,然后进行 5.0 / 2.0 // result5 的结果是 2.5 // 或者直接使用字面量 double result6 = 5.0 / 2; // 编译器会自动处理 // result6 的结果是 2.5
double 的常用数学函数
C 标准库 <math.h> 提供了丰富的数学函数,它们都接受 double 类型的参数并返回 double 类型的结果。
在使用这些函数时,记得在编译时链接数学库,例如在 Linux/macOS 下使用 -lm 选项:gcc your_program.c -o your_program -lm
| 函数 | 功能 | 示例 |
|---|---|---|
sqrt(x) |
计算 x 的平方根 |
sqrt(16.0) -> 0 |
pow(x, y) |
计算 x 的 y 次方 |
pow(2.0, 3.0) -> 0 |
sin(x), cos(x), tan(x) |
三角函数 (x 为弧度) | sin(3.1415926 / 2.0) -> ~1.0 |
log(x) |
自然对数 (ln) | log(2.71828) -> ~1.0 |
log10(x) |
常用对数 (log10) | log10(100.0) -> 0 |
fabs(x) |
x 的绝对值 |
fabs(-10.5) -> 5 |
ceil(x) |
向上取整 | ceil(2.3) -> 0 |
floor(x) |
向下取整 | floor(2.7) -> 0 |
代码示例:
#include <stdio.h>
#include <math.h>
int main() {
double x = 16.0;
double y = 2.0;
double angle = M_PI / 2.0; // M_PI 是 math.h 中定义的 π 值
printf("sqrt(%.1f) = %.2f\n", x, sqrt(x));
printf("%.1f 的 %.1f 次方 = %.2f\n", x, y, pow(x, y));
printf("sin(π/2) = %.2f\n", sin(angle));
printf("ceil(2.3) = %.1f\n", ceil(2.3));
printf("floor(-2.7) = %.1f\n", floor(-2.7));
return 0;
}
输入和输出
使用 printf 和 scanf 函数来处理 double 的输入输出。
-
输出 (
printf):- 使用格式说明符
%f来打印double。 %lf是scanf中用于读取double的格式说明符,在printf中使用%f和%lf效果是一样的(C99 标准后%lf在printf中也是有效的,但%f更通用)。- 可以使用 和数字来控制小数位数,如
%.2f表示保留两位小数。
- 使用格式说明符
-
输入 (
scanf):- 必须使用格式说明符
%lf来读取用户输入的double,使用%f是错误的,会导致读取失败和未定义行为。
- 必须使用格式说明符
代码示例:
#include <stdio.h>
int main() {
double price, tax_rate;
printf("请输入商品价格: ");
scanf("%lf", &price); // 注意这里必须是 %lf
printf("请输入税率 (0.08 表示8%%): ");
scanf("%lf", &tax_rate);
double total_price = price * (1 + tax_rate);
printf("------------------------------\n");
printf("商品价格: %.2f\n", price);
printf("税率: %.2f%%\n", tax_rate * 100);
printf("------------------------------\n");
printf("总价: %.2f\n", total_price); // 使用 %.2f 格式化输出
return 0;
}
- 用途:
double用于需要高精度小数运算的场景,如科学计算、金融、图形学等。 - 算术:支持 , , , 运算。
- 比较:支持
>,<, 等,但避免直接使用 ,应采用“容差法”进行比较。 - 混合运算:与
int混合时,int会自动提升为double。 - 陷阱:注意整数除法会先于浮点数转换发生,导致结果错误。
- 数学库:
<math.h>提供了强大的数学函数,编译时需加-lm。 - I/O:
printf用%f,scanf必须用%lf。
