嵌入式軟件開(kāi)發(fā)的基礎(chǔ)知識(shí)(4):數(shù)據(jù)表示和計(jì)算(1)
????因?yàn)楦↑c(diǎn)數(shù)運(yùn)算的時(shí)間開(kāi)銷非常大,所以在嵌入式幾乎不會(huì)使用浮點(diǎn)數(shù)進(jìn)行運(yùn)算。都是采用的定點(diǎn)運(yùn)算。這時(shí)對(duì)數(shù)據(jù)的格式就需要一個(gè)很大的要求。
定點(diǎn)表示:定點(diǎn)的小數(shù)點(diǎn)是確定的,浮點(diǎn)數(shù)的小數(shù)點(diǎn)是浮動(dòng)的。
舉個(gè)栗子:
????????如果變量A為Uint8類型數(shù)據(jù)。將小數(shù)點(diǎn)設(shè)定在低3位處,則記A數(shù)據(jù)為Q3格式數(shù)據(jù)。高5位表示整數(shù),低3位表示小數(shù)。小數(shù)的精度為:2^(-3), 也就是精度為0.125。整數(shù)部分最大值為:2^5-1=31。所以A的取值范圍為:0~31.875。
????當(dāng)然存在夸張的成分,但是實(shí)際上應(yīng)用中,一般是Uint32去表示Q10,Q16,Q24等常見(jiàn)的定點(diǎn)數(shù)據(jù)。也有Uint64表示Q30,Q38等數(shù)據(jù)。Qx后面的數(shù)字就表示使用低x位來(lái)表示小數(shù)。
定點(diǎn)運(yùn)算:定點(diǎn)格式數(shù)據(jù)的加減乘除
加/減法:量綱相同就直接相加/減法,不同需要移位來(lái)轉(zhuǎn)換量綱
乘法:Qm*Qn = Q(m+n):例如Q3*Q5=Q8
舉個(gè)例子:
????????為了方便計(jì)算,我們使用Uint8類型數(shù)據(jù)作為例子,做一個(gè)Q4的運(yùn)算(低四位表示小數(shù))
上述的式子中可以看出,定點(diǎn)計(jì)算出來(lái)的Q8數(shù)據(jù)和原數(shù)據(jù)是一致的。但是轉(zhuǎn)換到Q4之后,導(dǎo)致了精度損失,計(jì)算誤差為0.046875。(因?yàn)镼4的精度為0.0625)這個(gè)誤差至多為:1個(gè)精度(即0.0625)。精度損失是不可避免的,必然會(huì)向下取整(精度的整數(shù)倍)。
所以我們可以使用四舍五入,將誤差控制在半個(gè)精度之內(nèi)。四舍五入結(jié)果為:5.8125。四舍五入前的誤差為:0.046875。經(jīng)過(guò)了四舍五入之后,誤差為:0.015625。
簡(jiǎn)化一下四舍五入的方式(針對(duì)正數(shù)):對(duì)小數(shù)點(diǎn)后一個(gè)bit加1。
????????若不滿5:則bit位為0。加1之后,在位移之后會(huì)被舍棄。表現(xiàn)為四舍。
????????若滿5:則bit位為1,加1之后會(huì)進(jìn)位。所以右移之后,表現(xiàn)為五入。
好了,看似皆大歡喜了?。?!可是仔細(xì)觀察這個(gè)c_Q8。數(shù)據(jù)已經(jīng)達(dá)到了1484,如果使用Uint8來(lái)定義,那這早就溢出導(dǎo)致輸出錯(cuò)誤了。所以我們還需要另外的處理。
定點(diǎn)乘法運(yùn)算處理:
????????我們可以在小數(shù)點(diǎn)處截?cái)?,將a_Q4分為整數(shù)部分a1_Q0和小數(shù)部分a2_Q4計(jì)算。b_Q4同理。注意:量綱不同不能直接相加,但是可以直接相乘
這樣的下來(lái)的結(jié)果仍然是93,也就是5.8125。在計(jì)算過(guò)程中由于分開(kāi)計(jì)算,使用Uint8絕對(duì)不會(huì)溢出(只針對(duì)本情況)。
????????同理uint32的Q16格式,使用定點(diǎn)運(yùn)算也永遠(yuǎn)不會(huì)溢出。但是Uint32的Q24格式則不一定,因?yàn)閮蓚€(gè)小數(shù)相乘最大可以乘到Q48,導(dǎo)致溢出。這個(gè)時(shí)候小數(shù)相乘的部分需要額外的縮放處理。會(huì)造成額外的精度偏差。但是小數(shù)部分相乘本來(lái)就會(huì)右移24位。如果不最處理的話,最終結(jié)果精度可以保證在一個(gè)精度以內(nèi),對(duì)其做四舍五入操作,最終的的精度仍然能夠達(dá)到半個(gè)精度。
最后說(shuō)一句,我們程序全是定點(diǎn)運(yùn)算,不存在浮點(diǎn)數(shù)。EtherCat,Profinet之類的標(biāo)準(zhǔn)數(shù)據(jù)也全都是定點(diǎn)數(shù),不存在浮點(diǎn)數(shù)。所以源頭上沒(méi)有浮點(diǎn)數(shù),也不要在程序中聲明和使用浮點(diǎn)數(shù)。

寫東西實(shí)在是耗時(shí)