目录
[1. float关键字](#1. float关键字)
[1.1 取值范围与精度](#1.1 取值范围与精度)
[1.2 运算](#1.2 运算)
[1.2.1 加法运算](#1.2.1 加法运算)
[1.2.2 减法运算](#1.2.2 减法运算)
[1.2.3 乘法运算](#1.2.3 乘法运算)
[1.2.4 除法运算](#1.2.4 除法运算)
[1.3 输出](#1.3 输出)
[1.3.1 基本输出](#1.3.1 基本输出)
[1.3.2 控制小数位数](#1.3.2 控制小数位数)
[1.3.3 科学计数法输出](#1.3.3 科学计数法输出)
[1.3.4 控制字段宽度和对齐方式](#1.3.4 控制字段宽度和对齐方式)
[1.3.5 打印 float 类型的十六进制表示](#1.3.5 打印 float 类型的十六进制表示)
[1.3.6 输出特殊情况](#1.3.6 输出特殊情况)
1. float关键字
float 用于声明单精度浮点数变量,适用于需要表示较小范围浮动数值的场景。通常用于科学计算、物理模拟或财务计算等需要小数的应用。
语法示例:
cs
float a = 3.14f; // 声明并初始化一个 float 类型变量
注意,给float类型的变量赋值时,要在数值后面加上一个f或F,表示这是一个float类型的常量,否则默认为double类型的常量,可能会造成精度损失或编译警告,例如:
cs
float z = 2.71828f; //正确,使用float类型的常量赋值
float w = 2.71828; //不推荐,使用double类型的常量赋值,可能会损失精度或产生警告
1.1 取值范围与精度
float 通常使用 4 字节(32 位)存储。它基于 IEEE 754 浮点标准,包含 1 位符号位、8 位指数位和 23 位尾数位。这种表示方式使得 float 类型可以表示较小范围的数值,但精度有限。
- float 的有效位数约为 6 到 7 位数字。
- 表示范围大约是 -3.4 × 10^38 到 3.4 × 10^38。
具体结构:
cs
1位符号位 | 8位指数位 | 23 位尾数位(M,也称为有效数字)
S | E (8 bits) | M (23 bits)
符号位(S):表示数值的正负。
S = 0:表示正数。
S = 1:表示负数。
指数位(E):表示数值的幂,使用偏移量(Bias)表示。对于 float,偏移量为 127。指数的实际值是 E - 127,即:E = 00000000 表示指数为 -127(非标准化数)。
E = 11111111 表示指数为 +128(特殊数,如无穷大和 NaN)。
尾数位(M):表示数值的有效数字部分,尾数通常被假设为一个带有隐式前导 1 的二进制小数(对于规范化的数),例如 1.101。尾数实际存储的是这个数字去掉前导 1 后的部分。
例如,我们表示一个浮点数 -3.14 时:
符号位:由于数值是负的,符号位 S = 1。
指数:3.14 在二进制中大约等于 1.1001001 × 2^1,因此指数为 1。偏移量为 127,所以实际存储的指数部分是 1 + 127 = 128,即二进制的 10000000。
尾数:表示数字 3.14 时,需要将它转换为二进制形式并去掉前导的 1(如果是规范化数)。假设转换后的尾数是 1.10010010000111111011011。
最终表现形式:
cs
S | E (8 bits) | M (23 bits)
1 | 10000000 | 10010010000111111011011
1.2 运算
float类型的变量可以进行各种算术运算,例如加减乘除、取余、自增自减等,例如:
1.2.1 加法运算
cs
#include <stdio.h>
int main() {
float a = 5.5, b = 2.3;
float result = a + b; // result = 7.8
printf("%f\n", result);
printf("%0.2f\n", result);
return 0;
}
1.2.2 减法运算
cs
#include <stdio.h>
int main() {
float a = 5.5, b = 2.3;
float result = a - b; // result = 3.2
printf("%f\n", result);
printf("%0.2f\n", result);
return 0;
}
1.2.3 乘法运算
cs
#include <stdio.h>
int main() {
float a = 5.5, b = 2.3;
float result = a * b; // result = 12.65
printf("%0.0f\n", result);
printf("%0.1f\n", result);
printf("%0.2f\n", result);
printf("%0f\n", result);
printf("%f\n", result);
return 0;
}
1.2.4 除法运算
cs
#include <stdio.h>
int main() {
float a = 5.5, b = 2.3;
float result = a / b; // result = 2.391304
printf("%0.0f\n", result);
printf("%0.1f\n", result);
printf("%0.2f\n", result);
printf("%0f\n", result);
printf("%f\n", result);
return 0;
}
由于浮点数的表示方式是近似的,所以在计算时可能会出现精度丢失。例如,某些小数无法用二进制精确表示,可能会导致结果误差。
cs
#include <stdio.h>
int main() {
float a = 0.1;
float b = 0.2;
float result = a + b;
printf("%f\n", result); // 输出可能为 0.300000 或 0.30000005,因浮点精度问题
return 0;
}
1.3 输出
上面我们也看到了,输出浮点数时,通常使用 printf 函数。你可以通过格式控制符指定输出的精度和格式。
1.3.1 基本输出
cs
#include <stdio.h>
int main() {
float num = 3.14159;
printf("%f\n", num); // 默认输出六位小数:3.141590
return 0;
}
1.3.2 控制小数位数
通过格式化输出控制浮点数的小数位数。比如,输出两位小数:
cs
#include <stdio.h>
int main() {
float num = 3.14159;
printf("%.2f\n", num); // 输出:3.14
return 0;
}
1.3.3 科学计数法输出
如果浮点数的值非常大或非常小,printf 会自动使用科学计数法表示,或者你可以强制它使用这种格式。
cs
#include <stdio.h>
int main() {
float num = 12345678.0;
printf("%e\n", num); // 输出:1.234568e+07
return 0;
}
1.3.4 控制字段宽度和对齐方式
你还可以控制输出的字段宽度和对齐方式。例如,确保输出浮点数占据 10 个字符的位置:
cs
#include <stdio.h>
int main() {
float num = 3.14159;
printf("%10.2f\n", num); // 输出: 3.14, 总宽度为 10
return 0;
}
- %10.2f 表示输出的浮点数占 10 个字符的位置,其中 .2 表示保留两位小数。
- 数字 10 会让输出对齐,即在数值前面填充空格。
1.3.5 打印 float 类型的十六进制表示
有时你可能想要查看浮点数的底层二进制表示。可以使用 %a
或 %A
输出浮点数的十六进制表示:
cs
#include <stdio.h>
int main() {
float num = 3.14159;
printf("%a\n", num); // 输出:0x1.91eb86p+1
return 0;
}
1.3.6 输出特殊情况
无穷大(Infinity)
如果浮点数运算超出了表示范围,C 语言会返回一个特殊的值------无穷大 (infinity)。例如,除以 0:
cs
#include <stdio.h>
int main() {
float num = 1.0 / 0.0;
printf("%f\n", num); // 输出:inf
return 0;
}
非数值(NaN)
当进行无效的数值操作时(例如 0 除以 0),会产生 "Not a Number"(NaN)。例如:
cs
#include <stdio.h>
int main() {
float num = 0.0 / 0.0;
printf("%f\n", num); // 输出:nan
return 0;
}
2. double关键字
在C语言中,double 是一个关键字,用来声明双精度浮点型变量。它是用于存储较大范围和更高精度的浮点数数据类型。与 float 类型相比,double 提供更高的精度和更大的数值范围,适用于需要更多精度的计算。
语法示例:
cs
double variable_name;
2.1 精度
double 的精度比 float 高,通常为 15-16 位有效数字,而 float 只有 6-7 位有效数字。
cs
#include <stdio.h>
int main() {
double num1 = 3.14159265358979; // 声明一个 double 类型的变量
double num2 = 2.71828182845904;
// 打印两个 double 类型的变量
printf("num1 = %lf\n", num1); // %lf 用于输出 double 类型的浮点数
printf("num2 = %.15f\n", num2); // 控制输出精度,显示15位小数
return 0;
}
在 printf 中打印 double 类型的值时,可以使用 lf 作为格式说明符。尽管 lf 用于 double 类型,float 类型通常也使用 lf 来输出,这是因为在 printf 函数中 float 参数会自动提升为 double 类型。
- %lf:打印 double 类型浮点数。
- %.nf:打印 double 类型浮点数并控制小数点后显示 n 位数字。
2.2 存储大小
在大多数平台上,double 占用 8 字节(64 位),而 float 占用 4 字节(32 位)。
2.3 数值范围
float 的范围:
- 最大值:大约是 3.4 × 10^38
- 最小值:大约是 1.4 × 10^−45
这意味着 float 类型可以表示从非常小(接近 0)到非常大的数,但其精度相对较低,适用于大多数不要求高精度的应用。
double 的范围:
- 最大值:大约是 1.7 × 10^308
- 最小值:大约是 5.0 × 10^−324
double 的数值范围比 float 更广,可以表示极大的数值,也可以表示非常接近 0 的小数。