標籤:

matlab的floor函數是否有bug?

如圖,同學在用matlab編程的時候偶然發現的這個問題。我用自己的r2009b版本試了一遍也存在把29取整取成28的現象,而且試驗其他數就沒有這個問題。這是否是內置floor函數的一個bug?

-----------------

感謝大家的回答,請問在編程時應當養成一些怎樣的習慣以避免碰到這類問題,導致程序出bug呢?


&>&> format long
&>&> 0.29*100
ans =
28.999999999999996
&>&> 0.58*100
ans =
57.999999999999993


很多回答已經提到了,這是浮點小數表示精度的問題。類似的問題還有很多:

FAQ - MATLAB Wiki

但是如何避免呢?

匿名用戶提到的用sym變數是一個方法,即floor(sym(0.29)*100),或者類似的方法。

另外一個方法就是手動用eps函數設置精度了,比如floor(0.29*100+eps(100))。

baffling... rounding error of not so small numbers

一般來講,有意識地設置精度應該是一個良好的習慣。感覺原來學C的時候這個問題尤其突出,而MATLAB里遇到的情況其實不多,久而久之已經被MATLAB慣壞了……


floor(0.29*100)=floor(28.999**)=28

因為小數部分是由若干個1/2^k的和來表示的(0.625=1/2+1/8)

但不難發現絕大多數的小數部分都沒有辦法做到(換言之,必須得無限項的和才能相等)而計算機存儲一個數據給的位置是定的,因此丟掉了後面的數據而存在誤差,因此計算機中0.29=0.2899***


計算機只認識0和1 !!!

整數轉為二進位一點沒問題,數值不存在一丁點損失。

但是對於小數,計算機只能通過2的負次冪無限逼近。

那0.29怎麼逼近呢?

2^-2 = 0.25 差0.04,繼續拼湊

2^-5 = 0.03125 差0.00875,繼續拼湊

。。。

。。。

最後計算機只能計算出一個無限逼近0.29的值,這個逼近的計算過程是循環過程,遇到剛好能湊齊的,直接break。但是如果遇到這樣逼近不了的就會無限循環下去。

所以才有了精度這個標準,如果在計算的過程中如果『『差』的值在這個精度範圍之內,那就break

同樣的,計算機計算開方也是湊出來的


這不是bug,只是精度問題,由於二進位限制,幾乎所有語言的float類型都是只能精確到某些位.


舍入誤差


手頭沒matlab.

你試試floor(sym(0.29*100))

或者

floor(sym("0.29*100"))

看能不能解決問題.


很奇怪,matlab原來在這個時候不是精確求解。

我一直以為matlab和mathematica這倆都是精確求解數值的。

原因上面都說了,是二進位和十進位換算問題。

你可以測試下 29 / 100 * 100 看看是多少。


推薦閱讀:

用於數學建模 安裝matlab 2014 需要安裝哪些組件?
為什麼不少程序員認為Matlab的語言設計不優雅甚至比較丑?能否舉出一些例子來說明?
matlab把數值數組轉成分立的字元組成的元胞數組?
初學matlab需要什麼基礎嗎?

TAG:編程 | MATLAB |