zoukankan      html  css  js  c++  java
  • 单片机浮点乘除法优化措施及防止分子数据溢出

            单片机以性价比为特点,随着能源行业的发展,单片机在数字能源中的运用越来越广泛。最近学习了如何低端机上实现浮点运算。


    1、前言

              目前,大多数的单片机不具有浮点运算单元(FPU)。

              TI公司的tms320f28335具有FPU,但是在进行一个浮点除法运算时,需要1.5us的时间,这在实时控制系统中是不太能接受的。

              不具有浮点运算的单片机,需要将浮点运算转换为可以接受的整形运算

    2、整形运算概述

               单片机主要分为8位机、16位机和32位机,使用最多的就是16位机。

               16位机中变量类型 int 是16位的,也就是说:16位机使用16位的0或者1组合表示数据。

                32位机中变量类型 int 是32位的,也就是说:32位机使用32位的0或者1组合表示数据。

    3、浮点数的近似转换

               在单片机中,浮点数乘除运算可以近似乘以一个整数然后除以2的n次方表示。

               例如:

               0.25 = 1 >> 2;

               0.5 = 1 >> 1;

               0.75 = 3 >>2;

                其他的浮点数以此类推。

                一个浮点数可以有多种近似替换的方案,每种替换方案的精度不一样。

                比如:

                         0.8 可以近似等于3>>2(0.75),也可以近似等于13>>4(0.8125);

                         明显可以看到,使用13>>4替换0.8比3>>2的精度要高些。但是前者更容易造成数据位溢出

    4、防止数据溢出

                步骤三的转换也是有前提条件的:变量乘了整数后防止数据超过最大值。

                如果整形变量是16位的,那么它乘以一个数后,它也必须是16位的,不能超出原有变量的数据类型的范围。

                下面测试案例:

    //定义变量类型
    unsigned int   a;
    unsigned int   b;
    unsigned long  c;
    unsigned int   d;
    
    //测试方法
        a = (1024*1024)>>10;
        b = ((long)(1024*1024))>>10;
        c = (1024*1024)>>10;
        d = __builtin_muluu(1024,1024)>>10;
    
    //编译警告
    Test.c:101:15: warning: integer overflow in expression
    Test.c:102:21: warning: integer overflow in expression
    Test.c:103:14: warning: integer overflow in expression
    
    //调试变量结果
    a = 0
    b = 0
    c = 0
    d = 1024

            在16位单片机的C编译器的作用下,由上面的测试结果显示,仅仅只有第四种输出正确结果。

            其他三种,不管是强制数据转换,还是设置为long型的变量,导致输出结果都不正确。

            可能:

                  在这款单片机中,内存的最大位数位16位吧,如果需要超出16位运算结果的数据,就会报错。

                  或者只能按照该单片机自带的函数处理数据吧。

    5、与浮点Q变换的区别

              浮点数a转为定点数b是:b = (int)a*2n

              定点数b转为浮点数a是:a = (float)a>>n

              Q变换固定了n的位数,因此,截断误差也是固定的。一般,Q变换是把浮点数全部转为定点数参与运算,最后转为才转为浮点数;

              上述提到的变换,截断误差取决于具体乘以的数和参数n;,这种变换,参与运算的等效为一个浮点数。


    注意事项:

            上述优化措施有一个很大的弊端,">>"运算很容易造成数据精度的丢失。

                当一个整数A,乘以一个比1/A还小的数的时候,经过位移运算后,变为零

                  比如:

                  对于系数0.75:

                  1*0.75 = 0.75   转化为  1*3>>2 = 0;          丢失数值0.75,相对误差100%

                  2*0.75 = 1.5     转化为  2*3>>2 = 1;      丢失数值0.5,相对误差为33.3%

                  10*0.75 = 7.5   转化为 10*3>>2 = 7;         丢失数值0.5,相对误差为6.6%

                  20*0.75 = 15    转化为 20*3>>2 = 15;      丢失数值0,相对误差为0%

                  100*0.75 = 75  转化为100*3>>2=75;        丢失数值0,相对误差为0%

                  200*0.75 = 150   转化为 200*3>>2 = 150;  丢失数值0,相对误差为0%

                  对于系数0.25:

                  1*0.25 = 0.25   转化为  1>>2 = 0;        丢失数值0.25,相对误差100%

                  2*0.25 = 0.5    转化为  2>>2 = 0;      丢失数值0.5,相对误差为100%

                  10*0.25 = 2.5   转化为 10>>2 = 2;       丢失数值0.5,相对误差为25%

                  20*0.25 = 5      转化为 20>>2 =  5;      丢失数值0,相对误差为0%

                  100*0.25 = 25   转化为100>>2=25;     丢失数值0,相对误差为0%;         

                  200*0.25 = 50   转化为 200>>2 = 50;  丢失数值0,相对误差为0%

                  对于系数0.125:

                  1*0.125 = 0.125   转化为  1>>3 = 0;    丢失数值0.125,相对误差100%

                  2*0.125 = 0.25      转化为  2>>3 = 0;丢失数值0.25,相对误差为100%

                  8*0.125 =  1          转化为 8>>3 = 1;    丢失数值0,相对误差为0%

                   9*0.125=1.125    转化为9>>3 = 1;       丢失数值0.125,相对误差为11.11%

                  10*0.125 = 1.25   转化为 10>>3 = 1;  丢失数值0.25,相对误差为20%

                  20*0.125 = 2.5       转化为 20>>3= 2;    丢失数值0,相对误差为20%

                  100*0.125 = 12.5  转化为100>>3=12;    丢失数值0.5,相对误差为4%

                  150*0.125 =18.75 转化为150>>3=18;   丢失数值0.75,相对误差为4%

                   180*0.125=22.5  转换为180>>3=22;    丢失数值0.5,相对误差为2.22%

                  200*0.125 = 25   转化为 200>>3= 25;        丢失数值0,相对误差为0%

            因此,

                  上述思路,对于乘同以小于1的系数(被乘数),需要整数A不能太小,


                总结:分子防溢出,系数防丢失,我太难了。

                  

         

  • 相关阅读:
    win10彻底永久关闭自动更新的方法
    kibana.yml配置
    完整记录安装elasticsearch的过程
    docker下nginx的安装
    centos7删除mysql
    21 | panic函数、recover函数以及defer语句 (上)
    07 | 数组和切片
    SNAPSHOT包上传nexus成功,下载失败
    extract method(提炼函数)
    枚举中不要再出现数字了
  • 原文地址:https://www.cnblogs.com/cjyc/p/15370809.html
Copyright © 2011-2022 走看看