由Python浮點數溢出問題到二進制

爲什麼說浮點數缺乏精確性? python中浮點數運算問題 - 知乎

問題描述中很清楚,0.1+0.1+0.1-0.3沒有得到結果0,而是溢出了(Python3.6中不會)。數字在計算機中都是用二進制保存的,那就應該用二進制解釋一下。

數字的二進制

我們目前使用的數字都是十進制,方便理解和運算;計算機的底層電路是用與或非電路設計的。它只能識別二進制,所以計算機中的數字用二進制來表示。(數字在計算機中以補碼形式保存,但以下內容用原碼解釋,容易理解)

整數二進制:01010101

  1. 位置數:右邊爲低位,末位記爲0位;左邊爲高位,從右向左依次增加1。
  2. 每位的數字只能是0或1,每位代表的大小爲該位的數字*2的N次方,N是位置數。若每一位的數字都是1,則從右到左每位表示的大小爲1,2,4,8,…,2^N,依次擴大二倍。
  3. 二進制數字代表的大小爲:對每一位二進制代表的大小進行求和
  4. 舉例:7的二進制是0111,12的二進制是1100等

浮點數二進制:01010101.01010101

  1. 浮點數同樣用二進制保存。整數部分和整數二進制相同,小數部分原理相同
  2. 小數部分:0位是1能代表120=11*2^0=1,小數點後第一位是1則能夠代表121=0.51*2^{-1}=0.5,小數點後第二位是1能夠代表122=0.251*2^{-2}=0.25,依次縮小2倍,原理同整數。

【問題1】二進制轉爲十進制數很簡單,那麼十進制如何轉爲二進制呢?

# 整數求二進制
# 1.每次除以2,記下商和餘數(以後用上一次的商除以2)
# 2.直到某次商等於0結束 
# 3.把餘數倒序書寫
12/2=6...0
6/2=3...0
3/2=1...1
1/2=0...112爲例,二進制爲1100

# 小數求二進制
# 1.每次乘以2,記下結果,並把整數和小數部分分離。(以後用上一次的小數部分乘以2)
# 2.直到某次小數部分爲0結束 
# 3.把整數部分正序書寫
0.625*2=1+0.25
0.25*2=0+0.5
0.5*2=1+0.00.625爲例,二進制爲0.101
0.4*2=0+0.8
0.8*2=1+0.6
0.6*2=1+0.2
0.2*2=0+0.4
0.4*2=0+0.8
...0.4爲例,它無法結束,二進制爲0.01100110...

【問題2】回到知乎問題,爲什麼說浮點數缺乏精確性,結果會溢出?

  • 答:如上題所述,0.4的二進制表示是無限循環,所以如果要精確表示0.4,計算機需要無限個二進制位才能做到。然而計算機的內存、CPU寄存器等等硬件單元都是有限的,只能表示有限的二進制位。總結一句話,浮點數缺乏精確性是實數的無限精度跟計算機的有限內存之間的矛盾。

P.S. 浮點數在計算機中是以科學記數法表示的:a*10^n,a是底數,n是指數。以64位雙精度爲例,底數佔52位,指數佔11位,另外還有1位符號位,因此浮點值只有52位的精度,所以會出現舍入錯誤。


參考資料:

  1. 爲什麼說浮點數缺乏精確性? python中浮點數運算問題 - 知乎
  2. 爲什麼說浮點數缺乏精確性? python中浮點數運算問題 - 陳偉的回答 - 知乎
  3. 爲什麼說浮點數缺乏精確性? python中浮點數運算問題 - 知乎 - 匿名用戶回答
發佈了79 篇原創文章 · 獲贊 92 · 訪問量 14萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章