工作中,经常需要在设备间互发数据。其中浮点数是最重要、使用最多的数据类型。
在使用机器人与其他设备通过总线通信收发数据的时候遇到了尴尬,机器人不能收发小数。一般的做法是将数据放大发送,然后接收方再缩小还原。舍弃后面不重要的数字完成通信,这是工程师的智慧。
不止机器人,还有许多诸如轴控卡之类的设备不能收发小数。这是不是真的呢?小数的收发有什么困难,让这些智能制造的明星设备趴窝?
首先需要了解一下什么是浮点数?
百度过程省略若干字。
浮点数是计算机中小数的一种表示方法,浮点就是浮动小数点的意思。分为单精度浮点数和双精度浮点数,这里以下说到的都是单精度浮点数。
单精度浮点数占用4个位元,也就是32bits。当前用到的浮点数是依据标准IEEE 754-2008编码的。
![5803e604126cdc6c00ef949edac0526c.png](https://img-blog.csdnimg.cn/img_convert/5803e604126cdc6c00ef949edac0526c.png)
第1位(D31,sign)表示正负,0表示正,1表示负。
中间8位(D30-D23,exponet)表示指数。
后面23位(D22-D0,mantissa)存储有效数位。有效数位一共有24位,只存储23位,因为最左边的数永远是1。这里牵涉的概念是“归一化”,感兴趣的请问百度。
四字节浮点数的数据传送顺序为先低字节后高字节,分为8个ASCII码传送。
很显然,联网的任何设备都具备传送ASCII码的能力,机器人不能收发浮点数是假的。不是硬件问题,那么就是软件问题。机器人可能认识收到的ASCII码。
怎么把小数变成二进制码?
本来想用520.1314这个数字做个计算,但是它用浮点数表示是520.13140869140625,这个有点难...
这是转换公式,转换的目标是10.25。
![881759c05d7910ea5c87ee21be1df216.png](https://img-blog.csdnimg.cn/img_convert/881759c05d7910ea5c87ee21be1df216.png)
先把10.25转换为二进制表示:1010.01 。
小数转换为二进制,整数部分和小数部分要分别转换。整数部分转换的口诀是“除2取余,逆序排列”,小数部分的转换口诀是“乘2取整,顺序排列”。
![5c668ea78014a806d012a105a0b37232.png](https://img-blog.csdnimg.cn/img_convert/5c668ea78014a806d012a105a0b37232.png)
1010.01规格化之后是1.01001×2^3 。
根据上面的公式计算:
- 符号位S=0
- 阶码E=130,二进制表示为10000010
- 尾码M=01001,补全23位尾数是0100 1000 0000 0000 0000 000
把以上的内容合并到一起就是10.25的编码:0 10000010 0100 1000 0000 0000 0000 000
可以去https://www.h-schmidt.net/FloatConverter/IEEE754.html验证一下。
![66311fc87ee2428f155d72fdf259cbd7.png](https://img-blog.csdnimg.cn/img_convert/66311fc87ee2428f155d72fdf259cbd7.png)
二进制码到浮点数的转换就是上面的逆过程
1 10000011 100 1001 0000 0000 0000 0000
符号位S=1,阶码E=10000011,尾码=100 1001 0000 0000 0000 0000 。
带入公式计算,上述结果为-25.125 。
用这种方式不用约定放大缩小的倍数,所以是无损。作为数据传送并没有比x1000的方式有优势,对程序标准化的意义更大一些,调试工作量略有下降。
用KRL写了一个二进制编码到实数的转换程序。能完成按标准的转换,周末在家,没有测试接收PLC发送的数据。既然有标准存在,大概率是可以用的。