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

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


正文


大家好,我是bug菌~


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


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


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


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


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


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


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


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



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


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




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


2


驗證一下不均勻


好了,講了這么多理論,多多少少得來點程序驗證一下:


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


結果并不相等,并且相差還不少。


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


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


3


非要判斷相等


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


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


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


那有沒有相對更好一點的辦法呢?


當然是有的,不然接下來沒得寫了。


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



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


于是對浮點的近似相等進行了算法上的修改,如下代碼所示:


解釋一下 :


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


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


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


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


最后


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


—— The End —



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