文章目录
一、float与double区别
1、存储空间
float为单精度浮点数,占 4 个字节,32 位二进制存储
double为双精度浮点数,占 8 个字节,64 位二进制存储
2、数值范围
double 类型使用更多的字节存储数据,因此其数值表示范围比 float 更广
编译器默认小数为double类型,当作为float类型时需在末尾加上f
默认情况下,小数打印显示六位有效数字(最后一位四舍五入)
float的范围为-3.40E+38 ~ +3.40E+38;
double的范围为-1.79E+308~+1.79E+308
俩者具体数值范围如下:
float f1_min = 1.18e-38f;
float f2_max = 3.4e+38f;
double d1_min = 2.23e-308;
double d2_max = 1.79e+308;
其中e+表示10的次方,e-表示0.1的次方
(例:3e2即为3×102=300;3e-2即为3×0.12=0.03)
3、精度
float的精度为6~7位
double的精度为15~16位
这里精度指的是数值的最后一位或者几位的有效性
也就是说,浮点数的最后一位或几位可能会出现误差或被截断
因此在进行单精度浮点数计算和数字处理时,需要注意有效数字的精度问题
4、运算速度
double 的精度更高,但消耗内存是 float 的两倍
在一些处理器上,执行 float 类型的运算速度比 double 类型更快。
5、使用场景
能用单精度时不要用双精度,以节约内存,加快运算速度
需要更高的精度和更广的数值范围,则应该选择double类型
需要更快的运算速度,则应该选择float类型
在实际应用中,一些科学计算、大数据处理等场景需要使用 double 类型,而一些嵌入式设备或对数据存储空间要求高的场景,可以使用 float 类型
二、浮点数存储方式
1.存储方式
float 与 double 在存储方式上都是遵从 IEEE 的规范
存储分为三个部分:
单精度:符号位(1bit)+指数部分(8bit)+尾数部分(23bit)
双精度:符号位(1bit)+指数部分(11bit)+尾数部分(52bit)
1.S符号位(Sign) : 代表正负,0为正,1为负
2.E指数位(Exponent):用于存储科学计数法中的指数数据,并且采用移位存储
3.M尾数部分(Mantissa):范围为[1,2)
指数部分与尾数部分按照二进制科学计数法存储
2.计算方法
以4.125为例
(1)、整数部分与小数部分转为二进制
4.125(10)=100.001(2)
附:小数部分转换方式
0.125×2=0.25 取整数部分0
0.25×2=0.5 取整数部分0
0.5×2=1 取整数部分1
即得001
(2)、转为科学计数法表示
100.001(2)=1.00001(2)×22
尾数部分:00001
指数部分:2
因指数部分含正负,在存储时需加上偏移量
其中单精度为127,双精度为1023
因此存储的指数部分为
单精度:127+2=129=10000001
双精度:1023+2=1025=010000000001
(3)、存储值
单精度:符号位(1bit)+指数部分(8bit)+尾数部分(23bit)
0 10000001 00001
双精度:符号位(1bit)+指数部分(11bit)+尾数部分(52bit)
0 10000000001 00001
(末尾补齐0)
二、溢出打印
直接赋值大于浮点型范围时会报错
但如果是强制转换赋值则会存储inf
这是因为在C99中,使用宏:float INFINITY对浮点数赋值
#define INFINITY ((float)(_HUGE_ENUF * _HUGE_ENUF))
在超出范围的时候用来表示“无穷大 (infinity 的缩写)”
同样,当存储值小于范围时会附加#DEN(在编译器中监视可查看)来表示指非规格化数(denormalizedvalue),因为数字过小(接近于零)无法表示为 1.M * 2^E 形式的数字
小于范围时不会进行报错,但会影响计算时间增长且不精准