JavaScript四捨五入的那些坑

前言

常常使用JavaScript用來處理數字的程序員都知道,JavaScript的Number.toFixed,這一函數,在格式化數字時,會自動進行四捨五入,例如:javascript

10.125.toFixed(2) ---> "10.13"

可是在某些狀況下,其四捨五入的結果,每每都不盡人意,例如:java

10.145.toFixed(2) ---> "10.14"

那爲什麼爲出現上述這種狀況,須要從進制談起。git

進制之謎

衆所周知,計算機在設計之初,出於各方面角度考慮,最終採用二進制的格式來存儲數據。而咱們平時對於數字所慣用的進制是十進制。用二進制的格式來存儲十進制的數據,必然會面臨進制的轉換,進制的轉換就會面臨精度的丟失。程序員

例如,對於⅓,對於三進制的數來講是0.1,而對於十進制來講,是0.333(3循環)。那對於三個⅓相加,對於三進制來講,就是一(逢三進一),而對於十進制來講,就是0.999(9循環)。github

一樣的狀況,也會出如今十進制和二進制的轉換中。當咱們在計算機中,聲明一個變量爲10.145,其實該數字做爲二進制保存在計算機中,並不真的是10.145。能夠經過Number.prototype.toPrecision方法來一探究竟。函數

Number.prototype.toPrecision方法以指定的精度返回該數值對象的字符串表示。spa

10.145.toPrecision(21) ---> "10.1449999999999995737"

所以就能夠解釋,爲何toFixed()方法返回的四捨五入的值,在某些狀況不符合預料。prototype

一樣,也告訴你們,浮點數的全部計算,加減乘除無一例外,在某些狀況下,都會出現不符合預料的狀況,最多見的如0.1+0.2,等等。設計

解決方案

針對上述狀況,我寫了一個簡單的庫,能夠知足數字的四捨五入需求。round-jscode

探索浮點數標準

和大部分語言不一樣,JavaScript目前對於數字的表示,只有一種類型,即Number,採用64位雙精度浮點數來表示一個數,其標準與大多數語言同樣,採用IEEE-754標準。IEEE-754下64位雙精度浮點數的標準,能夠用一張圖來表示,以下:

float.png

  • sign:表明符號,用1位來表示,即正數負數,1表明正數,0表明負數;

  • exponent:表明指數,底數爲2,用11位來表述;

  • fraction:真正的有效數字,用52位來表示。

最終,任何一個數,對於該標準,都使用以下公式來表示得出:

其中:

  • V:結果

  • S:上面的sign

  • M:有效數字fraction

  • E:上面的exponent

能夠看出,這個表示方法,相似十進制中的科學計數法。
對於這些概念,IEEE-754標準中還有許多規定,例如<1M<2,等等,更多細節就不展開了。

完。

相關文章
相關標籤/搜索