簡體   English   中英

JS浮點導致舍入不正確

[英]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)。 這只是簡單的更換Mathmath和傳球的精度。

如果要使用數字作為小數,請使用十進制庫,例如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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM