2017-10-16 54 views
3

我正在處理相對較小且簡單的數字。我第一次試圖做出四捨五入(數字後2個符號)與臭名昭着的toFixed。這是一個已知的問題:有時它不正確。但讓我印象深刻的是,它也可以不一致JS中的舍入:不一致和意外的行爲

(0.395).toFixed(2); // "0.40" 
(0.295).toFixed(2); // "0.29" 

這些數字都非常相似,數字後3個跡象,但不同的行爲。

所以,我決定切換到使用Math.round。不久,我遇到了另一個問題:

Math.round(0.35055 * 10000)/100; // produces 35.05 instead of 35.06 

Math.round也有問題嗎?那麼,應該使用什麼方法?

+0

FWIW最後一個問題發生在Math.round之前:'0.35055 * 10000' - >'3505.4999999999995' –

+0

爲什麼'0.35055 * 1000'等於'3505.4999999999995'而不是'3505.5'? – Manav

+0

檢查這些答案:[這裏](https://stackoverflow.com/q/5490687/1823841),[這裏](https://stackoverflow.com/q/10768083/1823841) –

回答

3

不幸的是,JavaScript已知存在如下精確問題,這些問題在以下問題中得到了更好的解釋:Is floating point math broken?,正如評論中指出的那樣。

如果您需要更高程度的數值準確性,我建議您使用庫,如BigNumber,它也有自己的toFixed方法。

你的例子是這個樣子:

var a = new BigNumber('0.35055'); 
a = a.times(10000) 
a = a.dividedBy(100) 
console.log(a.toFixed(2)); //would log "35.06" 

爲了簡便起見,你也可以連鎖經營,像這樣:a.times(10000).dividedBy(100).toFixed(2)

+1

我通過以下解決方法解決了我的問題: 'Math.round((0.35055 * 100)* 100)/ 100;' 但顯然,您的解決方案更好,謝謝。 – Zaziro

1

我想這是事先設計好的。請記住,這些數字存儲在基數2中,因此在轉換爲基數10時會損失精度。如果您想了解這些轉換爲什麼看起來不一致,則必須查看這些轉換。如果您想精確保留固定的小數位數,則可以使用整數進行操作並僅轉換用於顯示。