近來工作中發現了一種浮點數運算的近似算法,也不知道前人有沒有這樣應用過,反正自己到目前還沒見過,就暫且稱作自己發現的。如有類同,純屬巧合。本算法對嵌入式編程的人有很大用處,其他領域就不知道了。現整理如下,希望對需要的人有所幫助。 -
大家都知道,乘法相對好運算些,也有現成的公式可以分解、簡化,使其運算簡單符合自己的要求,但除法有時卻找不到什么公式可以把它分解的符合自己的要求,特別是對做8位機編程的人,浮點數運算很占空間又影響執行速度,所以一般都需要化成整數進行運算
舉例如下:
10位AD采集,最大值是1023,如果需要利用AD采集結果對輸出進行連續控制,就需要對AD進行細分,假設細分500份,那么每份就是1023/500=2.046,假如只取整數部分,則最大值時會有較大誤差,假如用浮點數則輸出 =
實際值/2.046,但8位MCU不喜歡浮點數,那么此時就要換一種方法,如下:
1.把最大值分為可被細分數整除的整數部分+小數部分,如被500除1023可分為1000+23;被300除可分為900+123;
2.把能被整除的整數部分除以除數得出最小細分整數部分,如1000/500=2;900/300=3;
3.把實測數除以最小細分數得得出修正前的整數;
4.把修正前的整數乘以步驟1中的尾數部分再除以滿刻度值,得出修正數,把修正前的數減去修正數得出最終所需倍數,既所需要的結果;另外滿刻度值最好是根據實際取一定的舍取值。例如,如果10位AD可取1000(其實取滿刻度值應該除以1023,至于取1000是為了使偏差減小,不至于使輸出結果超調),如果是8位AD可取250(其滿刻度值是255,取250也是為了在采集值快達到滿刻度值時防止輸出結果超調,當然直接使用滿刻度值也是可以的,為了防止超調要對輸出結果做一個限幅).
例如1:對10位AD,滿刻度1023分成500份,1023可分成1000+23,令z=1023/500=2.046,假設當前實測值x是635,那么此實測值x對應的輸出值應是y=x/2.046=635/2.046=310,假如MCU不采用浮點數,z=1023/500=2,那么MCU算出的輸出值是y=x/2=635/2=317,比實際值大了7個點;按照上面的公式,把y乘以尾數23除以1000得出修正數w=y×23/1000=317×23/1000=7,按照步驟5把y減去修正數即得出與實際沒有誤差的結果y-w=317-7=310;
例如2:對于8位AD,滿刻度255分成100份,255可分成200+55,令z=255/100=2.55,假設當前實測值x是226,那么此實測值x對應的輸出值應是y=x/2.55=226/2.55=88,假如MCU不采用浮點數,z=255/100=2,那么MCU算出的輸出值是y=x/2=226/2=113,比實際值大了25個點;按照上面的公式,把y乘以尾數55除以250得出修正數w=y×55/250=113×55/250=24,按照步驟5把y減去修正數即得出與實際沒有誤差的結果y-w=113-24=89 ,與88只差一個點;假設當前實測值x是滿刻度值255,那么此實測值x對應的輸出值應是y=x/2.55=255/2.55=100,假如MCU不采用浮點數,z=255/100=2,那么MCU算出的輸出值是y=x/2=255/2=127,比實際值大了27個點;按照上面的公式,把y乘以尾數55除以250得出修正數w=y×55/250=127×55/250=27,按照步驟5把y減去修正數即得出與實際沒有誤差的結果y-w=127-17=100 ,沒有誤差不會超調。 如有異議請指正。以上純屬個人經驗,對套用出錯者不負任何責任,如若轉載請注明出處!
|