1. 浮点数在内存中的存储方式
浮点数在内存中的存储方式为:符号位、指数、尾数(小数)。具体如下表格:
类型 | 符号位 | 指数 | 尾数(小数) |
---|
float | 1位(第31位) | 8位(第23~30位) | 23位(第0~22位) | double | 1位(第63位) | 11位(第52~62位) | 52位(第0~51位) |
float和double都是浮点数类型,float占4字节内存,double占8字节内存,所以他们所能表示的数据范围和精度不一样而已。但是,它们在计算机内部的存储方式是完全一样的。另外,浮点数是没有unsigned类型的,即浮点数是没有无符号类型的。
2. 浮点数的转换
2.1 浮点数的转换有3点
- 将浮点数转换为二进制
- 用科学计数法表示二进制浮点数
- 计算指数偏移后的值
注意:计算指数时,要加上偏移量的,而加上的偏移量的值与类型有关。其实float偏移量加上127,而double类型偏移量的值则加上1023。
例如:我们得到了指数是6,然后偏移后的值则是:
float:127 + 6 = 133
double:1023 + 6 = 1029
2.2 10进制浮点数在内存的表示计算示例
32.25这个浮点数在内存如何表示?
如何验证我们的推算的结果是正确的呢?
我们可以设计一段代码验证,如下:
#include <stdio.h>
int main(void)
{
float f = 32.25;
unsigned int *p = (unsigned int *)&f;
printf("0x%08x\n", *p);
return 0;
}
我们把这段代码编译运行后,打印结果是:0x42010000,这充分说明了我们的推算结果是正确的。
3. 关于浮点数的一些思考
int类型的表示范围:-2^31 ~ 2^31 - 1
float类型的范围:-3.4 * 10^38 ~ 3.4 * 10^38
float类型和int类型它们所占用的内存都是4个字节,但是为什么float类型比int类型的表示范围大很多?
首先,它们所占据的内存都是4个字节,说明都是只有32个0和1的组合,所以它们所能表示的数字的个数肯定是一样的。但是float类型所表示的范围却大很多,那么只能说明float类型所表示的数据是不连续的。
不连续如何理解?比如1、2、3、4、5我们可以说表示的范围是1-5,而且是连续的。但是同样,1、3、5、7、9也是表示了5个数,但是表示范围却有1-9,表示范围扩大了,但是表示的个数依然只有5个。所以float类型表示的范围变大了,说明float表示的数据是不连续的。而且这个间隔是没有规律的,数据越大的时候,间隔还会越来越大。
我们可以使用如下代码验证这一结论:
#include <stdio.h>
int main(void)
{
float f = 123456789;
printf("f = %f\n", f);
return 0;
}
上述代码最终打印输出的是f = 123456792.000000, 而不是f = 123456789.000000。这里就可以看出,浮点数出现了跳跃的情况,即浮点数是不连续的。
4. 总结
- int类型与float类型都是占据4字节内存,所以都是32个0和1的组合,所以它们所能表示的数据个数是相同的;
- 浮点数所表示的数据是不连续的;
- 浮点数只是一种近似表示法,是不能用作精确数来使用的(比如条件判断 if (f == 0.1) 这种判断不要出现);
- 浮点数的内存表示方法更复杂,所以浮点数的运算比int类型要慢很多。
|