www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當(dāng)前位置:首頁 > 公眾號精選 > 嵌入式客棧
[導(dǎo)讀]正文大家好,我是bug菌~最近進(jìn)行代碼的review過程中看到同事在代碼中直接拿浮點(diǎn)數(shù)相等來作為條件,其他同事提醒他的時候,他還迷迷糊糊不知道為什么,所以就有了今天這篇文章。1浮點(diǎn)數(shù)據(jù)的不均勻我們經(jīng)常會談到浮點(diǎn)數(shù)的精度問題,float-單精度,double-雙精度,double類...


正文


大家好,我是bug菌~


最近進(jìn)行代碼的review過程中看到同事在代碼中直接拿浮點(diǎn)數(shù)相等來作為條件,其他同事提醒他的時候,他還迷迷糊糊不知道為什么,所以就有了今天這篇文章。1


浮點(diǎn)數(shù)據(jù)的不均勻


我們經(jīng)常會談到浮點(diǎn)數(shù)的精度問題,float-單精度,double-雙精度,double類型相比float類型精度更高,相應(yīng)的需要的內(nèi)存字節(jié)個數(shù)也越多,談到精度的問題,其實(shí)也就說明這種數(shù)據(jù)類型并不能夠連續(xù)的標(biāo)識任何的點(diǎn),整形數(shù)就不用說了,小數(shù)部分直接不能標(biāo)識,對于浮點(diǎn)數(shù)的一些知識其實(shí)bug菌在很早之前就有過介紹過:


【典藏】別怪"浮點(diǎn)數(shù)"太坑(C語言版本)


毒王這篇文章基本上可以從浮點(diǎn)數(shù)的存儲到表意來較好的認(rèn)識浮點(diǎn)數(shù)數(shù)據(jù)類型,但是中間部分對于浮點(diǎn)數(shù)精度部分的介紹并不是很形象,所以今天再詳細(xì)一點(diǎn)說明一下。


首先我們要認(rèn)識到通常float類型的變量占據(jù)四個字節(jié),而uint32_t的整形類型也是占據(jù)四個字節(jié),既然都是四個字節(jié),那他們所能表示的不同數(shù)據(jù)個數(shù)是一樣的。


如果不太理解,可以把float看成4個bit,uint32_t也是4個bit,那么他們不管經(jīng)過什么變換,每個數(shù)據(jù)類型都只能夠標(biāo)識16個數(shù)。


好,如下圖以4字節(jié)float的數(shù)據(jù)存儲模型所示:



4個字節(jié)的浮點(diǎn)數(shù),不像無符號整形所有的bit都是數(shù)據(jù)區(qū),并且以每個數(shù)據(jù)之間相差1均勻分布,而浮點(diǎn)數(shù)把這4個字節(jié)分為了不同的區(qū)來起到不同的作用,從而用另外一種方式表達(dá)數(shù)據(jù)。


其指數(shù)部分越大,表示的數(shù)據(jù)就越大,但是尾數(shù)部分只能表示到23位,這樣的話導(dǎo)致數(shù)據(jù)的精度就越差,如果不太理解可以用一個較大的數(shù)通過上面的轉(zhuǎn)換方式進(jìn)行換算,便能理解。




所以同樣是4個字節(jié),根據(jù)浮點(diǎn)數(shù)的表示,越接近0就越稠密,越遠(yuǎn)離0就越稀疏,呈現(xiàn)一種不均勻的數(shù)據(jù)排列狀態(tài),如上圖所示,同樣它也也不能標(biāo)識實(shí)軸上任意的點(diǎn)。


2


驗(yàn)證一下不均勻


好了,講了這么多理論,多多少少得來點(diǎn)程序驗(yàn)證一下:


看看上面的代碼,這還用說,肯定這兩個數(shù)相等呀,相減也等于0,然而看一下輸出結(jié)果:


結(jié)果并不相等,并且相差還不少。


其結(jié)果也就說明了浮點(diǎn)數(shù)在大數(shù)的標(biāo)識精度不好,只能近似標(biāo)識,同時也說明了為什么一般不使用浮點(diǎn)數(shù)相等來進(jìn)行判斷的原因。


這也是為什么有時候明明我們采用直接編碼用準(zhǔn)確的浮點(diǎn)數(shù),到了浮點(diǎn)數(shù)變量里面卻損失了精度,因?yàn)?個字節(jié)的float標(biāo)識不了,只能近似處理。


3


非要判斷相等


由于有些應(yīng)用非要使用浮點(diǎn)數(shù)進(jìn)行相等的處理,我們不應(yīng)該直接使用浮點(diǎn)數(shù)進(jìn)行等于號的判斷,而是要在一定的誤差和精度范圍內(nèi)進(jìn)行滿足。


如上圖所示代碼是比較常用的處理辦法,在往期的文章中,bug菌沒有詳細(xì)的講解這個誤差宏的定義,前面了解到當(dāng)數(shù)據(jù)比較大的時候相鄰的差值會比較大,這樣就存在兩個浮點(diǎn)數(shù)的差值大于所設(shè)置的誤差范圍而無法判斷相等。


所以這樣的處理辦法來判斷浮點(diǎn)數(shù)近似相等會存在一些局限性。


那有沒有相對更好一點(diǎn)的辦法呢?


當(dāng)然是有的,不然接下來沒得寫了。


還是要從浮點(diǎn)數(shù)的存儲和標(biāo)識出發(fā)來處理該問題,既然浮點(diǎn)數(shù)天然就存在一定的誤差,而有時候計算又無法獲得唯一的數(shù)值,如下圖所示,浮點(diǎn)數(shù)計算出來的實(shí)軸上的值都會因?yàn)楦↑c(diǎn)數(shù)無法存儲標(biāo)識而近似到其相鄰的可以標(biāo)識的數(shù)值上。



從浮點(diǎn)的存儲模型來看,指數(shù)部分代表著浮點(diǎn)數(shù)的范圍,尾數(shù)部分代表著浮點(diǎn)數(shù)的精度,那么尾數(shù)的最后一位其實(shí)就表示了浮點(diǎn)數(shù)的當(dāng)前數(shù)值附近的精度。


于是對浮點(diǎn)的近似相等進(jìn)行了算法上的修改,如下代碼所示:


解釋一下 :


如果直接相等,說明浮點(diǎn)數(shù)各數(shù)據(jù)位都相等;而如果不相等可能相鄰,于是強(qiáng)制轉(zhuǎn)化為整形,比較尾數(shù)最后一位是否不同。


這里使用一個小技巧,采用異或的處理辦法,如果其他位都相同,而最后一位不同,結(jié)果就等于1,認(rèn)為兩個浮點(diǎn)數(shù)近似相等。


本文到此結(jié)束,我相信大家應(yīng)該對浮點(diǎn)數(shù)有了一個更加深入的了解,面對一些問題心中也會有一些答案,比如浮點(diǎn)數(shù)為什么不能作為switch的參數(shù),也是同樣的原因。


但總的來說還是建議大家不要判斷浮點(diǎn)數(shù)相等,非要用也要特別小心。


最后


好了,今天就跟大家分享這么多了,如果你覺得有所收獲,一定記得點(diǎn)個~


—— The End —



本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
關(guān)閉
關(guān)閉