浮點數在計算機程式設計中一定會使用,然而使用中會有很多坑。最近做機械臂就被跳到坑里了。機械臂三自由度反解出來的cos值比1大一點點,1.00000...4。就是這一點點,坑了我一晚上,坑了師兄一上午。計算公式沒問題,求解程式沒問題,就是算出來的值有問題!後來才反應到是浮點數儲存造成的。
舉乙個最簡單的浮點數儲存影響的例子。
double targetvalue = 0.21上面的程式,按照我們想想的,while迴圈將執行21次,之後counter和targetvalue相等,迴圈結束。;double counter = 0
;int
main()
return0;
}
但是事實上,執行的時候並不是這樣。這裡我擷取幾個vs除錯的變數值來說明。
首次進入迴圈前,可以看到targetvalue的值並不是我們設定的0.21,而是0.20999...
在每次相加時,counter也不是加0.01,而是和0.01差距很小的乙個數,經過20次相加之後並不是0.2,而有差距。
當相加21次時,兩個數並不相等,所以無法退出迴圈。
可以看出,浮點數並不如我們認為的那麼精確。實際上,造成這個的原因是因為計算機的儲存機制造成的。計算機使用二進位制儲存資料,那麼對於0.21這個數,下面是轉換的過程,乘二取整法。
0.21*2=0.42 整數為0 -> 0.0
0.42*2=0.84 整數為0 -> 0.00
0.84*2=1.68 整數為1 -> 0.001
0.68*2=1.36 整數為1 -> 0.0011
0.36*2=0.72 整數為0 -> 0.00110
最後可以表示為:
0.0011010111000010…
可以看出,轉換成二進位制之後,是乙個無限的數,不能精確的表示出來。所以就造成了這個bug。這也是我們程式中,cos算出來超過1一點點的原因。我在matlab裡還原了c++的演算法,matlab計算出的數值就是1,沒有任何小數。
對於上面比較的問題,很多人都知道解決方法,那就是兩個浮點數求差,差值很小就認為相等。程式如下:
double targetvalue = 0.21關於cos計算的bug,我最後採取的手段是將浮點數保留5位小數,精度能夠符合我們的要求,而且不會被浮點數儲存影響。;double counter = 0
;int
main()
return0;
}
計算機上的坑真的多,爭取畢業前多踩,多填坑。
浮點數精度問題
一 例子 首先我們去編譯器試試 double a 1.9 通過新增監視檢視a的值 會發現a的值是1.8999999 二 開始今天的學習 在最開始學c 的時候並沒有對浮點數進行很深入的學習,認為浮點不就是小數嘛,首先在c 的巨集裡面有 flt max 和 flt min 的定義,float是四位元組的...
浮點數精度之謎
話要從業務 裡的bug說起,大致過程是前端運算 2.07 1 之後結果卻是1.0699999999999998,老司機們都知道是浮點數運算的精度丟失導致的,在檢視了下具體 果然處理不當。因此我深究一番,並誕生了此文。此處重點強調兩個認識誤區 首先不得不說說浮點數的表示方法,任何數在計算機面前都會被處...
PHP 浮點數的精度
浮點數的精度有限。儘管取決於系統,php 通常使用 ieee 754 雙精度格式,則由於取整而導致的最大相對誤差為 1.11e 16。非基本數 算可能會給出更大誤差,並且要考慮到進行復合運算時的誤差傳遞。此外,以十進位制能夠精確表示的有理數如 0.1 或 0.7,無論有多少尾數都不能被內部所使用的二...