為什麼說浮點數缺乏精確性? python中浮點數運算問題

來源:互聯網
上載者:User
python中的運算為什麼結果接近零而不為零 是什麼原因造成的? 浮點數缺乏精確性應該怎麼解釋? 為什麼前兩個運算式沒出現問題 最後一個出現了問題? 請教

回複內容:

這是因為小數以二進位形式表示時的有窮性導致的。(下面的說法,不完全準確,只是協助理解)

以下是之前我在另一個地方對一個類似問題的解答,因為內容差不多,就直接搬過來了(本人略懶,希望有所協助):

#################################此處開始####################################

我們知道,將一個小數轉化為二進位表示的方式是,不斷的乘2,取其中的整數部分。例如:
+----------------------------------------------------------------------------------------------------------------------------------+
(1) 0.625*2 = 1.25, 整數部分為1,小數部分為0.25
(2) 0.25 * 2 = 0.5 , 整數部分為0,小數部分為0.5
(3) 0.5 * 2 = 1 , 整數部分為1,小數部分為0
+----------------------------------------------------------------------------------------------------------------------------------+
所以0.625的二進位表示就是0.101。


然而有些小數,例如0.4,並不能夠精確的轉化為二進位表示,用上面的這種方法計算:
+----------------------------------------------------------------------------------------------------------------------------------+
(1) 0.4*2=0.8 整數部分為0,小數部分為0.8
(2) 0.8*2=1.6 整數部分為1,小數部分為0.6
(3) 0.6*2=1.2 整數部分為1,小數部分為0.2
(4) 0.2*2=0.4 整數部分為0,小數部分為0.4


(5) 0.4*2=0.8 整數部分為0,小數部分為0.8
(6) 0.8*2=1.6 整數部分為1,小數部分為0.6
(7) 0.6*2=1.2 整數部分為1,小數部分為0.2
……
+----------------------------------------------------------------------------------------------------------------------------------+
所以0.4轉化為二進位,應該是0.0110... 這樣一個無限迴圈小數。

電腦的記憶體、cpu寄存器等等這些硬體單元都是有限的只能表示有限位元的二進位位,因此儲存的二進位小數就會和實際轉換而成的位元有一定的誤差。(你可以試著將0.3轉化為二進位表示,也將出現一個迴圈小數。)

實際上,大多數情況下,小數在電腦中是以一種類似科學計數法的形式表示的,具體的可以參考一下其他的資料。但即便如此,仍然存在誤差。


所以在python中不建議直接將兩個浮點數進行大小比較,或者做精確的計算,往往會得到意想不到的結果。當然,如果非要用,可以參考decimal模組的相關內容。請將十進位數字0.1轉換成二進位浮點數。這不是Python的問題,而是實數的無限精度跟電腦的有限記憶體之間的矛盾。

舉個例子,假如說我只能使用整數(即只精確到個位,電腦內的浮點數也只有有限精度,以C語言中的雙精確度浮點數double為例,精度為52個二進位位),要表示任意實數(無限精度)的時候我就只能通過舍入(rounding)來近似表示。
比如1.2我會表示成1,2.4表示成2,3.6表示成4.
所以呢?
在算1.2 - 1.2的時候,由於電腦表示的問題,我算的實際上是1 - 1,結果是0,碰巧蒙對了;
在算1.2 + 1.2 - 2.4的時候,由於電腦表示的問題,我算的實際上是1 + 1 - 2,結果是0,再次蒙對了;
但是在算1.2 + 1.2 + 1.2 - 3.6的時候,由於電腦表示的問題,我算的實際上是1 + 1 + 1 - 4,結果是-1,運氣沒那麼好啦!

這裡的1.2, 2.4, 3.6就相當於你問題裡的0.1, 0.2和0.3,1, 2, 4則是真正在電腦內部進行運算的數值,我說清楚了嗎?

其他請看IEEE 754浮點數標準,比如CSAPP第二章啥的(雖然估計你沒興趣看)

另:不僅僅是浮點數的在電腦內部的表示有誤差,運算本身也可能會有誤差。比如整數2可以在電腦內準確表示,但是要算根號2就有誤差了;再比如兩個浮點數相除,本來兩個數都是精確表示的,但除的結果精度卻超出了電腦內實數的表示範圍,然後就有誤差了。
電腦智能處理可數集合的運算,但是全體實數是不可數的,所以電腦只能用一些奇怪的方法來擬合他,於是就產生了浮點數。這個不是python 的問題,所有基於二進位的浮點數都會有這個問題,原因在於大部分浮點數轉換為二進位後都是無限迴圈小數,而浮點數不可能用無限大的記憶體來儲存,所以會有舍入的誤差
詳細可以看代碼之謎(五)來個 @vczh 答案的通俗版,比如用 10 個箱子裝100個球,規定每個箱子只能裝一個球,那顯然是裝不下所有球的。類似,double類型是 64bit 的,最多能表達 2^64 個數,實數有多少呢?無數個,所以 double 類型是裝不下所有實數的,只能表達一個近似值。9.4. decimal電腦所有資訊的儲存使用二進位表示,像 @vczh 所說,有限的「位」,無法表示無數個數,那麼,小數用二進位標記法,只能表示那些能被寫成 的數。

0.1 的二進位表示為 0.000110011[0011]...,因為是無限迴圈的,無法用有限的位表示,所以電腦系統會進行舍入,以求用最接近的值來表示,這裡涉及到不同的舍入方式,具體請見深入理解電腦系統,本答案也是參考該書。大白話版的很多人都說了,就是電腦有限的數字表示不了數學中無窮的數。

樓主如果有一定電腦或者數學基礎可以搜一下IEEE754,電腦是如何表示浮點數的一種協議。看懂了那個協議就知道為什麼了~

如果看不懂IEEE754那就需要研究下數學中各種進位~主要是二進位、十進位和他們的關係。自傲的人類!有本事你直接喂它2進位數,看看還有沒有這種精度問題。
  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.