0.1 + 0.2 != 0.3背後的原理

初學JavaScript,在進行小數(浮點數)運算時,常常會碰到這樣的狀況:0.1 + 0.2=0.30000000000000004,記得當時,教程告訴咱們說,0.1 + 0.2在JavaScript運算中,它的值是不固定的,能夠在後面學習和試驗中,漸漸發現,這個值彷佛每次都是0.30000000000000004,因而漸漸懷疑當時學習過程當中關於它的和值是不固定的說法。前端


其實有必定編程基礎的同窗們應該都知道,計算機是採用二進制來表示十進制的,規則是:整數除以2,商繼續除以2,獲得0爲止,將餘數逆序排列;小數乘以2,取整,小數部分繼續乘以2,取整,獲得小數部分0爲止,將整數順序排列。例如:
整數轉二進制小數轉二進制面試

其實無論是十進制轉二進制仍是八進制、十六進制,原理都是同樣的,即,基數連連除(整數)或者連乘(小數)進制轉換編程

再回到咱們最初的問題, JS 採用 IEEE 754 雙精度版本(64位),而且只要採用 IEEE 754 的語言都有前面的問題。post

IEEE 754 標準是IEEE浮點數算術標準(IEEE Standard for Floating-Point Arithmetic)的標準編號 ,等同於國際標準ISO/IEC/IEEE 60559 。IEEE 754 標準規定了計算機程序設計環境中的二進制和十進制的浮點數之間的交換、算術格式以及方法 。

根據前面介紹的知識,0.1 的二進制表示爲:學習

0.1 = 2^-4 * 1.10011(0011)// (0011) 表示循環

0.2 的二進制表示爲:spa

0.2 = 2^-3 * 1.10011(0011)// (0011) 表示循環

前面說了,JS 採用 IEEE 754 雙精度版本(64位),六十四位中符號位佔一位,整數位佔十一位,其他五十二位都爲小數位。由於 0.1 和 0.2 都是無限循環的二進制,因此在小數位末尾處須要判斷是否進位(規則和十進制裏的四捨五入同樣)。
因此 0.1的二進制表示(0.1 = 2^-4 * 1.10011(0011)) 進位後就變成了 2^-4 * 1.10011(0011 * 12次)010,同理可得0.2的二進制表示 。把這兩個二進制加起來獲得 2^-2 * 1.0011(0011 * 11次)0100 , 這個值再換算成十進制就是 0.30000000000000004設計


因此說,0.1 + 0.2=0.30000000000000004,在JavaScript中,它的結果並不是不固定的。3d

那麼,若是須要比較0.1 + 0.20.3的關係,咱們又該如何進行呢?
其實對於在大學學過數學分析、數值逼近或者高中課程代數方面證實知識的同窗來講,天然能夠想到讓0.1 + 0.2的和減去0.3小於一個任意小的數,好比說咱們能夠經過他們差值是否小於0.0000000001來判斷他們是否相等。JavaScript也提供了一些原生的方法,好比toFixed() 方法可把 Number 四捨五入爲指定小數位數的數字,語法:NumberObject.toFixed(num)code

參數描述:num,必需。規定小數的位數,是 0 ~ 20 之間的值,包括 0 和 20,有些實現能夠支持更大的數值範圍。若是省略了該參數,將用 0 代替。

參考內容:JavaScript toFixed() 方法
幾道高級前端面試題解析blog

相關文章
相關標籤/搜索