Simulink中浮点数的优化表示法
本次内容【思想】将带大家认识Simulink定点数,下面将分别介绍定点数的理论基础、Simulink中实现过程及定点数的应用场合。
理论基础
在介绍定点数之前,需要先科普下计算机中的数据(整形、浮点型)的存储方式。
从最简单的8位整型开始,不考虑正负数的情况下,二进制数从0000 0000~1111 1111(8个位)表示0~255。如何考虑正负符号,就需要引入补码,用最高位来标记正负号。0000 0000 ~0111 1111表示0~127;1000 0000~11111111表示-1~-128。整型数据的表达很好理解,浮点型数据就稍微麻烦点。根据IEEE(电气和电子工程师协会)对32位浮点数的定义如下:
在一个32位的内存空间中,最高位用来表示正负符号,接下来的8位用来表示整数部分,最后的23位用来表示小数部分。
计算的方法就是把8位整数部分的值与23位小数部分的值共同表达浮点型数据。
定点数的原理就是根据上面的方法,定义不同内存空间中整数与小数部分的长度来实现浮点型数据的表达。假设我们可以试图利用8位的内存空间来表示浮点数:
正数形式
如果用最低1位来表示小数位,则0111 1111代表的是+63.5
如果用最低2位来表示小数位,则0111 1111代表的是+31.75
如果用最低3位来表示小数位,则0111 1111代表的是+15.875
如果用最低4位来表示小数位,则0111 1111代表的是+7.9375
负数形式
如果用最低1位来表示小数位,则1111 1111代表的是-0.5
如果用最低2位来表示小数位,则1111 1111代表的是-0.25
如果用最低3位来表示小数位,则1111 1111代表的是-0.125
如果用最低4位来表示小数位,则1111 1111代表的是-0.0625
Simulink中的实现
Simulink专门用于数据类型转换的模型,Data Type Converison
在输出的数据类型中可以看到除了常见的int/float/double类型外还有fixdt的定点数据类型,支持三种类型的定点数。
可以通过Matlab强大的帮助文件了解fixdt的使用。例如:fixdt(1,16,8),其中第一个参数1表示是否有符号【1:有、2:没有】;第二个参数16表示当前用来表述整个浮点数的数据长度为16位;最后一个参数8表示用来表述小数部分的数据长度为8位。定点数的存储可以为策略工程师提供灵活的浮点数管理方式。
定点数的应用场合
如果看过之前纯电动仿真控制策略文章《AVL-CRUISE纯电动仿真策略提高教程》的朋友肯定对这个有印象。仿真工程师将输入的信号统一转换为double数据类型,再进行策略逻辑运算。但是,在嵌入式工程师看来,这种行为简直是【败家子】。在复杂的控制算法模型中,一方面,如果所有的浮点型数据都直接用double或者float,单片机内存堆栈根本无法放下这么多内容。另一方面,实际的控制工程不需要使用到double这么高的数据精度。
例如在Simulink中同样表示0.5数值,可以用8位、16位甚至32位,但是它们占用内存的大小却有所不同!
根据前面生成代码的建模方式《Simulink代码生成应用教程》,创建一个简单的算法,同时对这个算法生成C语言代码。
可以看到在生成的结果中,模型中常量模块中的0.5浮点型数据已经被整型数据所取代。
其实在实际应用过程中,数据精度并不是越高越好,数据精度高意味着付出的内存资源更多。因此,在内存紧张的嵌入式系统中,工程师可以通过定点数的方式找到一个精度和资源之间的平衡点。