[英]Javascript toFixed() is not working as expected
我正在使用toFixed
但是該方法無法按預期運行
parseFloat(19373.315).toFixed(2);
//19373.31 Chrome
預期產量:19373.32
parseFloat(9373.315).toFixed(2);
// 9373.32 Working fine
為什么第一個示例向下取整,而第二個示例向上取整?
問題在於大多數小數部分的二進制浮點表示形式不准確。 19373.315的內部表示實際上可能類似於19373.314999999,因此toFixed向下取整,而19373.315可能為19373.315000001,向上取整。
為什么第一個示例向下取整,而第二個示例向上取整?
查看內存中兩個值的二進制表示形式。
const farr = new Float64Array(2); farr[0] = 19373.315; farr[1] = 9373.315; const uarr = new Uint32Array(farr.buffer); console.log(farr[0], uarr[1].toString(2).padStart(32, 0) + uarr[0].toString(2).padStart(32, 0)); console.log(farr[1], uarr[3].toString(2).padStart(32, 0) + uarr[2].toString(2).padStart(32, 0));
在不深入細節的情況下,我們可以看到第二個值的末尾有一個額外的“ 1”,當它適合64位時,會在第一個較大的值中丟失。
假設固定轉換為32位浮點型; 檢查此實用程序...
19373.315以32位浮點格式存儲為19373.314453125(錯誤-0.000546875)。
盡管(19373.315).toFixed(4)
結果為19373.3150
。
即使這是“預期的”或“預期的”,我仍將其報告為錯誤。
在四舍五入檢查期間應使用雙精度,因此在轉換為固定字符串期間應進行適當的四舍五入。
我認為規范甚至是這樣說的。 :\\
在V8 javascript引擎源代碼中, Number.prototype.toFixed
函數在此文件中調用DoubleToFixedCString
...
那里可能有一些不適當的優化...(正在研究它。)
我建議為V8額外提交一個測試案例,具體為 19373.315。
(19373.3150).toFixed(39)
得出19373.314999999998690327629446983337402343750。
舍入一次會使其達到19373.315(這是正確的),但是舍入到兩位數時不會出現在正確的數字上。
我認為這里應該進行第二次四舍五入,以捕獲像這樣的邊緣情況。 我想可能有舍入到n+1
再次數字,然后n
數字。 也許還有其他一些聰明的方法可以解決它。
function toFixedFixed(a,n) { return (a|0) + parseFloat((a % 1).toFixed(n+1)).toFixed(n).substr(1); } console.log(toFixedFixed(19373.315,2)); // "19373.32" console.log(toFixedFixed(19373.315,3)); // "19373.315" console.log(toFixedFixed(19373.315,4)); // "19373.3150" console.log(toFixedFixed(19373.315,37)); // "19373.3149999999986903276294469833374023438" console.log(toFixedFixed(19373.315,38)); // "19373.31499999999869032762944698333740234375" console.log(toFixedFixed(19373.315,39)); // "19373.314999999998690327629446983337402343750"
(摘自我對Vahid Rahmani的回答的評論,誰是正確的。)
其他答案也解釋了為什么,我建議使用像numeric.js這樣的庫,它將按您期望的那樣處理。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.