你不會知道編程語言會把0.1+0.2算成多少
- 2019 年 10 月 28 日
- 筆記
開你的 Python,輸入「0.1+0.2=」,結果是多少?0.30000000000000004 對不對?為什麼結果不是 0.3?本文作者給出了詳細的解釋。
從小我們就知道 0.1 + 0.2=0.3。但是,在光怪陸離的計算世界中,運算方式卻大相徑庭。
我最近開始用 JavaScript 進行編碼,在閱讀數據類型時,我注意到 0.1 + 0.2 不等於 0.3 的奇怪行為。我向 Stack Overflow 尋求幫助,在上面找到了一些有用的帖子。如下圖所示:

Stack Overflow 界面圖像。
經過大量的研究和數學運算後,我得出結論,這不是錯誤。這是數學運算中的浮點運算。讓我們進一步了解內在機制。
問題描述:為什麼 0.1 + 0.2 = 0.30000000000000004?
如果你用 Java 或 C 語言編過程,那你一定知道用於存儲值的不同數據類型。我們在前面的討論中將考慮兩種數據類型:整數型和浮點型。
整數型存儲整數,而浮點型存儲小數。
在這之前,我們先來了解一個小概念:為了實現計算,數字是如何表示的?極小數和極大數通常用科學計數法表示,即:

同樣,如果一個用科學計數法書寫的數字小數點前有一個非零的十進制數,則該數字是標準化寫法。例如,0.0005606 用科學計數法的標準化寫法為:

Significant 是指不包含零的有效數字,base 表示所使用的進制——此處為十進制(10)。Exponent(指數)表示小數點需要向左或向右移動的步數。
現在,有兩種顯示浮點數的方法:單精度和雙精度。在進行浮點運算時,單精度使用 32 位,而雙精度使用 64 位。
與許多其他編程語言不同,JavaScript 並未定義不同類型的數字數據類型,而是始終遵循國際 IEEE 754 標準,將數字存儲為雙精度浮點數。
這種格式以 64 位存儲數字,其中數字(分數)存儲在位 0 到 51 中,指數存儲在位 52 到 62 中,符號存儲在位 63 中。

IEEE754 雙精度標準。
我們按 IEEE754 標準用 64 位表示 0.1。第一步是將十進制的 0.1 轉換為二進制的 0.1。首先將 0.1 乘以 2,然後將小數點前的數字分離出來,得到其相應的二進制數。

重複此操作至 64 位。然後把它們按升序排列,獲取尾數,再根據雙精度標準,我們將把其四捨五入到 52 位。

尾數
用科學計數法表示二進制 0.1 並只保留前 52 位:

尾數部分處理好後。現在我們用下面的方式處理指數:

這裡,11 代表我們要使用的 64 位表示的指數位數,-4 代表科學計數中的指數。
所以最終數字 0.1 的表示形式是:

同理,0.2 表示為:

將兩個數相加,得到:

轉換為浮點數,它變成:

這就是 0.1 + 0.2 = 0.30000000000000004 的原因。
本文轉載自機器之心 原文鏈接:https://medium.com/better-programming/why-is-0-1-0-2-not-equal-to-0-3-in-most-programming-languages-99432310d476