原文鏈接: https://www.cnblogs.com/yalong/p/15762637.html
項目中使用 toFixed 出現的問題:
一. js報錯 Uncaught SyntaxError: Invalid or unexpected token
如下圖所示:
就是說對 整數 和 字符串 使用toFixed() 會報錯
二. 四舍五入不正確
1.335.toFixed(2) // 輸出 1.33
四舍五入的問題在谷歌、火狐瀏覽器下都存在,ie瀏覽器下正常
三. 偶爾數字出現特別長的情況,如下圖所示:
問題分析
問題一其實是toFixed的使用問題
x.toFixed(n) 方法可把 Number類型的數字x 四舍五入為指定小數位數的數字, n為保留的小數位數,並且返回的結果是字符串類型
注意這里x 必須為數字Number類型,如果用字符串的話報錯
3.toFixed(2)
也會報錯,原因是js引擎在運行的時候,默認將3后面的那個點認為是小數點,所以3.toFixed()也就相當於3.0toFixed(), 所以報錯
解決方法如下:
- 多加一個點:
3..toFixed(2) // 輸出 3.00
- 把數字存一個變量上
let num = 3
num.toFixed(2) // 輸出 3.00
- 用括號:
(3).toFixed(2) // 輸出 3.00
問題二是瀏覽器本身toFixed() 的計算有問題
解決辦法可以重寫瀏覽器的toFixed()函數,寫法網上很多就不多介紹了
問題三的本質是js小數的精度問題
看下面的示例:
// 加法 =====================
0.1 + 0.2 = 0.30000000000000004
0.7 + 0.1 = 0.7999999999999999
0.2 + 0.4 = 0.6000000000000001
// 減法 =====================
1.5 - 1.2 = 0.30000000000000004
0.3 - 0.2 = 0.09999999999999998
// 乘法 =====================
19.9 * 100 = 1989.9999999999998
0.8 * 3 = 2.4000000000000004
// 除法 =====================
0.3 / 0.1 = 2.9999999999999996
0.69 / 10 = 0.06899999999999999
這個問題的原因簡單來說就是計算機計算的時候,會先把10進制的小數轉為2進制的機器編碼,然后使用二進制的編碼進行計算,最后再把二進制的結果轉為10進制。
10進制小數轉2進制小數的過程如下:
十進制的小數轉換為二進制小數,主要是利用小數部分乘2,取整數部分,直至小數點后為0
以0.625為例, 如下圖所示:
十進制的 0.625 轉為二進制 就是 0.101
但是有些小數轉為二進制的時候,最后一位永遠不會是0,然后就變成"無限長度"的了
看下面例子:
0.1 + 0.2 = 0.30000000000000004
把0.1 和 0.2 轉成二進制如下:
0.1 -> 0.0001100110011001...(無限)
0.2 -> 0.0011001100110011...(無限)
IEEE 754 標准的 64 位雙精度浮點數的小數部分最多支持 53 位二進制位,所以兩者相加之后得到二進制為:
0.0100110011001100110011001100110011001100110011001100
因浮點數小數位的限制而截斷的二進制數字,再轉換為十進制,就成了 0.30000000000000004。
誤差就是這么出現了
總結
瀏覽器的toFixed() 存在的問題如下:
- 四舍五入不准確,並且在不同瀏覽器下也存在差異
- 有時會出現小數的精度特別長的情況,當然這個的本質其實是小數的精度問題
對於以上的問題,可以把toFixed() 方法重寫了, 也可以使用別人的輪子,比如: bignumber
參考鏈接:
https://www.cnblogs.com/chyshy/p/14745284.html
https://www.cnblogs.com/bettermu/p/8532460.html
https://juejin.cn/post/6844903572979597319
https://jingyan.baidu.com/article/eb9f7b6dc692e9c79264e878.html