为什么说单精度float 浮点数的精度只有7位 ?
这个解释起来轻松一点,精度这里指的是最大有效数字的位数,即只需要考虑尾数部分就可以啦。
对于float类型,尾数部分是23,转换成10进制的精度,223=10x223=10x –> x=23log2≈6.92 x=23log2≈6.92,所以23位2进制最多只能表示6位10进制数,这里就是头文件中FLT_DIG=6的来由。
但还有一种说法,也是网上的主流说法,二进制小数点的第一位永远都是1,可以省略,实际上二进制的精度为24,所以10进制的精度为7。
---------------------
单精度浮点数所能表示数据的范围:以传统的32位为依据 不是IEEE754 的指数形式。
指数位 占用 8位 (包含一位符号位) 尾数部分 占用24位(包含一位符号位)
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
1 1 |
1 2 |
1 3 |
1 4 |
1 5 |
1 6 |
1 7 |
1 8 |
1 9 |
2 0 |
2 1 |
2 2 |
2 3 |
2 4 |
2 5 |
2 6 |
2 7 |
2 8 |
2 9 |
3 0 |
3 1 |
3 2 |
尾数部分(含有一位符号位) |
指数部分(含有一位符号位) |
浮点数IEEE754标准的表示法:
IEEE754规定:
(1)单精度浮点数字长32位,尾数长度23,指数长度8,指数偏移量127;双精度浮点数字长64位,尾数长度52,指数长度11,指数偏移量1023;
(2)约定小数点左边隐含有一位,通常这位数是1,所以上述单精度尾数长度实际为24(默认省略小数点左边的1则为23),双精度尾数长度实际为53(默认省略小数点左边的1则为53)
---------------------
例子1 176.0625 用IEEE754 标准格式表示:
整数部分 10110000
小数部分 0001
所以用二进制表示十进制的176.0625 的 形式为:
10110000.0001 表示为
因为 IEEE754 约定单精度的指数的偏移量为 127
所以指数为 127+7=134 用二进制表示为:1000 0110
因为IEEE754 约定尾数的长度为 23 由于尾数 1.01100000001小数点左侧的1是省略的,
所以 尾数的 表示形式 为 0110 0000 0010 0000 0000 000
共23位
因为是整数,符号位为0
所以176.0625 以IEEE754标准在内存中的存放形式为
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
1 1 |
1 2 |
1 3 |
1 4 |
1 5 |
1 6 |
1 7 |
1 8 |
1 9 |
2 0 |
2 1 |
2 2 |
2 3 |
2 4 |
2 5 |
2 6 |
2 7 |
2 8 |
2 9 |
3 0 |
3 1 |
3 2 |
符号位 |
指数部分(含127偏移量) |
尾数部分 |
|||||||||||||||||||||||||||||
0 |
1 |
0 |
0 |
0 |
0 |
1 |
1 |
0 |
0 |
1 |
1 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
例子2
把23.7度用IEEE-754 表示出来
23对应的二进制为 10111
十进制0.7 对应的小数部分为:
乘以2 |
取整数 |
余小数 |
|||
0.72=1.4 |
1 |
0.4 |
|||
0.42=0.8 |
0 |
0.8 |
|||
0.82=1.6 |
1 |
0.6 |
|||
0.62=1.2 |
1 |
0.2 |
|||
0.22=0.4 |
0 |
0.4 |
|||
0.42=0.8 |
0 |
0.8 |
|||
0.82=1.6 |
1 |
0.6 |
|||
0.62=1.2 |
1 |
0.2 |
|||
0.22=0.4 |
0 |
0.4 |
|||
0.42=0.8 |
0 |
0.8 |
|||
0.82=1.6 |
1 |
0.6 |
|||
0.62=1.2 |
1 |
0.2 |
|||
0.22=0.4 |
0 |
0.4 |
|||
0.42=0.8 |
0 |
0.8 |
|||
0.82=1.6 |
1 |
0.6 |
|||
0.62=1.2 |
1 |
0.2 |
|||
0.22=0.4 |
0 |
0.4 |
|||
观察到用二进制表示十进制小数0.7 出现了 循环
十进制的23.7度用二进制表示
10111.10110 0110 0110 0110 0110 0110 0110 0110
把上面的数表示成规范化小数形式
1.0111 1011 0011 0011 0011 001
故23位的尾数为
0111 1011 0011 0011 0011 001
指数为4 加上偏移量127 为131 对应 1000 0011
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
1 0 |
1 1 |
1 2 |
1 3 |
1 4 |
1 5 |
1 6 |
1 7 |
1 8 |
1 9 |
2 0 |
2 1 |
2 2 |
2 3 |
2 4 |
2 5 |
2 6 |
2 7 |
2 8 |
2 9 |
3 0 |
3 1 |
3 2 |
符号位 |
指数部分(含有偏移量127) |
尾数部分 |
|||||||||||||||||||||||||||||
0 |
1 |
0 |
0 |
0 |
0 |
0 |
1 |
1 |
0 |
1 |
1 |
1 |
1 |
0 |
1 |
1 |
0 |
0 |
1 |
1 |
0 |
0 |
1 |
1 |
0 |
0 |
1 |
1 |
0 |
0 |
1 |
对应16进制数 |
|||||||||||||||||||||||||||||||
4 |
1 |
B |
D |
9 |
9 |
9 |
9 |
对应的16进制为 41BD 9999
我用多路温度测试仪器 用485接口读取 触点1的温度, 当温度 显示 23.7时
我用串口监控器读取上来的数据为 01 04 04 41 BD 99 9A 95 A7 95 A7是MODBUS CRC16 的校验码。
当多路温度测温仪显示的温度为24摄氏度的时候,我用串口监控器读取的数据为
01 04 04 41 C0 00 00 EF 84 EF 84 为Modbus crc16 的校验码
现在开始 把IEEE-754 表示的数 翻译成十进制的小数
0100 0001 1100 0000 0000 0000 0000 0000
上面的绿色为指数部分 100 00011 对应十进制的131 减去偏移量127 等于 4
小数部分 加上省略的1 应该为
1.100 0000 0000 0000 0000
乘以指数4以后 变为
11000.0000 0000 0000
.0 摄氏度。
原文地址:https://www.cnblogs.com/bailongwei654321/p/12228425.html