![](/img/trans.png)
[英]JS floating point causing incorrect rounding - Math.round() always works?
[英]JS floating point causing incorrect rounding
我有可能是一個極端情況。 當嘗試將值4.015
到小數點后4.015
,我總是以4.01
結尾,而不是期望的4.02
。 對於以.015
為小數部分的所有數字,都會發生這種情況。
我在JS中使用一種相當普通的方法進行處理:
val = Math.round(val * 100) / 100;
我認為問題是乘以100時開始的。浮點數不准確導致此值四舍五入而不是向上取整。
var a = 4.015, // 4.015
mult = a * 100, // 401.49999999999994 (the issue)
round = Math.round(mult), // 401
result = round / 100; // 4.01 (expected 4.02)
小提琴: http : //jsfiddle.net/eVXRL/
如果我嘗試舍入為4.025
則不會發生此問題。 確實返回了4.03
的期望值; 到目前為止,這只是.015
的問題。
有沒有辦法優雅地解決這個問題? 當然,只是尋找.015
並一次性處理該案例是很.015
,但這似乎是錯誤的!
浮點數不是實數 ,而是浮點數。
實數是無限的,但是只能用有限的位數來表示它們,因此有時,如果所需的確切數不能在浮點系統中表示,則必須存在一些舍入誤差。
因此,在處理浮點數時,必須考慮到的是,您不會想到完全相同的數字。
如果您需要一個確切的數字,則應該使用一個可以提供更高精度的庫,通常它將使用定點和/或符號表示法
有關更多信息,請參見Wikipedia分頁以及此文章(有點復雜,但很重要): 每位計算機科學家應了解的浮點運算法則
我最終使用math.js進行數學運算,從而解決了我所有的浮點問題。
該lib的優點在於,無需實例化任何類型的Big Decimal對象(即使該lib確實支持BigDecimal)。 這只是簡單的更換Math
與math
和傳球的精度。
如果要使用數字作為小數,請使用十進制庫,例如big.js。
大多數語言(包括javascript)中的浮點值都以二進制表示形式存儲。 通常,這就是您期望的。 在這種情況下,您的4.015將轉換為二進制字符串,並且碰巧被編碼為您看到的4.014999999 ...值,這是雙精度(8字節)IEEE754值中可用的最接近的二進制表示形式。
如果您正在做金融數學或人類消費數學(即小數),那么您將需要4.015舍入到4.02,並且需要一個十進制庫。
由於新的IEEE754-2008標准包括decimal32等作為十進制浮點值表示形式,因此計划在javascript中包含浮點值的十進制表示形式(例如here )。 有關更多信息,請參見: http : //speleotrove.com/decimal/
最后,如果您使用javascript進行會計數學運算(即不應意外產生或消失金錢的財務計算),則請以整分/便士進行所有計算。
您可以使用正則表達式提取並替換數字以獲得所需的內容:
val = (val + "").replace(/^([0-9]+\.[0-9])([0-9])([0-9]).*$/, function(whole, head, lastdigit, followup) {
if(followup >= 5) {
return head + ("" + (parseInt(lastdigit) + 1));
}else return head + lastdigit;
});
否則,您可以使用val = val.toFixed(2)
但特定的值4.015給出4.01(4.0151給出4.02作為“預期”)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.