浮点数的表示法
浮点数在内存中的存储方式为:符号位、指数、尾数。
类型 | 符号位 | 指数 | 尾数 |
---|---|---|---|
float | 1位(第31位) | 8位(第23-30位) | 23位(第0-22位) |
double | 1位(第63位) | 11位(第52-62位) | 52位(第0-51位) |
十进制浮点数在计算机内部的转换
转换步骤:
1. 将浮点数的整数部分和小数部分分别转换为二进制
2. 用科学计数法表示二进制浮点数
3. 计算指数偏移后的值
注意:
计算指数时需要加上偏移量,而偏移量的值与类型有关。
示例:对于指数6,偏移后的值如下:
float:127 + 6 = 123
double:1023 + 6 = 1029
转换举例:8.25在内存中的float表示
8.25的二进制表示:1000.01 -> 1.00001 * (2^3)
符号位:0
指数:3 + 127 = 130 -> 10000010
尾数:00001
故内存中8.25的float表示为:
0 10000010 00001000000000000000000 -> 0x41040000
浮点数隐藏的秘密(今天的主要内容)
首先,我们来看一个有趣的问题。
int类型的范围:[-231, 231 - 1]
float类型的范围:[-3.4 * 1038, 3.4 * 1038]
思考:
int和float都占4个字节,为什么float表示的范围要远大于int?
要弄清这个问题,需要知道以下几点:
1、数据类型所占用的字节数仅仅决定了该类型所能表示的具体数字的个数,而不是数的最大值和最小值
2、float所能表示的数字个数和int相同
3、float可表示的数字之间是有间隙的,是不连续的,故它能表示的范围比int大得多
由以上几点我们可以得出结论:float只是一种近似的表示法,不能作为精确值使用。实际上,double与float具有相同的内存表示法,所以以上几点同样适用于double,只不过double占用的位数比float多,因此其精度相对于float要高。
在本篇博文结束前,写一段代码验证上述结论:
#include <stdio.h>
int main()
{
float f = 3.1415F;
float f1 = 123456789;
printf("%0.10f\n", f); //期望值:3.1415000000
printf("%0.10f\n", f1); //期望值:123456789.0000000000
return 0;
}
在linux中编译运行,结果如图,与预期值均不符合,说明float表示的值的确是有间隙、不连续的。