目录
一、编码格式
二、取值分类
三、范围及精度
3.1 范围
3.2 精度
四、运算方式:
4.1 加减法运算
4.2 乘除法运算
五、常见的坑及处理方法
5.1 输出数据与输入数据不一致
5.2 浮点数据的比较运算
5.3.浮点数据与整形数据强制转换的问题
大家都知道C语言中的浮点数据有取值范围广、计算不易溢出、可使用小数等优点,所以在编码中会常用到。但实际上浮点数据是有很多坑的,只有深入了解浮点数据的编码结构才能在工作中避免误用浮点数据。
本文以C语言单精度(float类型)为例,详细讲解一下浮点数据的格式、范围、精度、计算方法及常见的问题。双精度浮点(double类型)数据与之类似,本文不再做详细分析。
一、编码格式
C语言中的浮点数据类型采用的是工业标准IEEE754,单精度(float类型)32位数据的编码格式如下所示,由左向右分别为bit31~bit0。
符号位S(bit31):表示浮点数正负,1—负数,0—正数;
阶码E(bit23~bit30):阶码部分(指数部分),长度为8bit,采用移码的编码方式,偏移量为127。
比如,10进制数字“1”用偏移量为127的移码表示为:127+1=128=0x80=1000000b。
注:当阶码为全0时,表示非规格化数据,阶码表示十进制数(-126)。
尾数M(bit0~bit22):尾数部分(底数部分),采用二进制小数原码编码,小数点在最高位(bit22)之前。在规格化数据中,通过平移保证二进制个位为1,既该部分表示为1.xxxxxxxxxxxxxxxxxxxxxxxb, 比如10进制0.75,转化为二进制小数为0.11B,左移1位为1.1b,尾数仅取小数点后部分,尾数二进制表示为.10000000000000000000000b。 在非规格化数据中尾数二进制个位数为0。比如,非规格化尾数.10000000000000000000000b表示10进制数0.5。
二、取值分类
单精度(float类型)浮点分类如下表:
单精度分类
十进制Dex与Float类型的转换公式
数据个数
规格化数据
(阶码二进制值不全为0也不全为1,尾数补1)
Dex=(-1)*S (1.0b+0.Mb)*2^(E-127)
--1
=4261412863个数据
注:+0和-0是不同的编码,故此处减去个1。
非规格化数据:
(阶码二进制全为0,此时指数真值为:1-偏移量=1-127=-126,尾数没有补1)
Dex=(-1)*S (0.Mb)*2^(-126)
个数据
特殊值1
(阶码二进制为全1)
尾数部分全0,符合位为0表示正无穷。
尾数部分全0,符合位为1表示负无穷。
2个数据
尾数不为0,表示NaN,不存在的数
(-2)个数据
转换举例
例1:十进制10.75转换成float格式的编码
第一步:取符号位,10.75为正数,故符号位S为0。
第二步:将十进制数据转换为二进制,10.75=1010.11b。
第三步:二进制1010.11b右移3位为1.01011b。
阶码(指数)部分应该为3,用移码表示3:E=127+3=130=0x82H=10000010b,
尾数(底数)部分为.