單片機浮點乘除法優化措施及防止分子數據溢出


        單片機以性價比為特點,隨着能源行業的發展,單片機在數字能源中的運用越來越廣泛。最近學習了如何低端機上實現浮點運算。


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不能太小,


            總結:分子防溢出,系數防丟失,我太難了。

              

     

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM