簡體   English   中英

檢查十進制浮點數

[英]checking decimal floating point number

通常我們期望0.1+0.2===0.3為真。 但這不是javascript的結果。 由於javascript顯示十進制浮點數,但在內部存儲二進制浮點數。 因此,這將返回false。

如果我們使用chrome開發人員工具控制台,則會得到以下結果:

0.1+0.2;//0.30000000000000004

0.1+1-1;//0.10000000000000009


0.1 + 0.2 === 0.3 ;// returns false but we expect to be true.
0.1+1-1===0.1;//returns false

由於舍入錯誤,作為最佳實踐,我們不應直接比較非整數。 取而代之的是,將舍入誤差的上限考慮在內。 這樣的上限稱為機器ε。

這是epsilon方法:

var eps = Math.pow(2,-53);
function checkEq(x,y){
    return Math.abs(x - y) <  eps;
}

現在,如果我們檢查它返回true。

checkEq(0.1+0.2,0.3);// returns true
checkEq(0.1+1-1,0.1);//returns true

沒關系,很好。 但是如果我檢查一下:

checkEq(0.3+0.6,0.9);// returns false

這不行,也不符合我們的預期。

那么,我們應該如何返回正確的結果呢?


我試圖解決的問題是這樣的:

var lx,ly,lxi,lyi;
function isFloating(x){
   return x.toString().indexOf('.');
}
function checkEq(x,y){
   lxi = x.toString().length - x.toString().indexOf('.') - 1;
   lyi = y.toString().length - y.toString().indexOf('.') - 1;
   lx = isFloating(x) > -1 ? lxi : 0;
   ly = isFloating(y) > -1 ? lyi : 0;
   return x.toFixed(lx) - y.toFixed(ly)===0;
}

現在,修復。 如果我這樣檢查,結果很好:

checkEq(0.3,0.3); //returns true

但是以下返回false

checkEq(0.3+0.6,0.9)

此處首先將其值存儲在binaray浮點數中,然后在計算后返回十進制浮點數。

所以現在,我如何才能為每個輸入設置toFixed()方法,例如在checkEq(0.3+0.6,0.9) 0.3.toFixed(lx) and 0.6.toFixed(lx) ,然后僅添加:

    var lx,ly,lxi,lyi;
    function isFloating(x){
    return x.toString().indexOf('.');
    }
    function checkEq(x,y){
    x = x.toString().split(/\+ | \- | \/ | \ | \\ */);
    y = x.toString().split(/\+ | \- | \/ | \ | \\*/);

    for(var i=0;i<x.length,y.length;i++){
    //here too I may be wrong...
       lxi = x[i].toString().length - x[i].toString().indexOf('.') - 1;
       lyi = y[i].toString().length - y[i].toString().indexOf('.') - 1;
    // particularly after this would wrong...
       lx = isFloating(x[i]) > -1 ? lxi : 0; 
       ly = isFloating(y[i]) > -1 ? lyi : 0;

    //And, here I'm stucked too badly...
    //take splitted operators to calculate:
    //Ex- '0.3 + 1 - 1' 
    // Number('0.3').toFixed(1) + Number('1').toFixed(0) - Number('1').toFixed(0)
    //But careful, we may not know how many input will be there....


    }

//return x.toFixed(lx) - y.toFixed(ly)===0;
}

也歡迎提供其他答案,但是非常感謝您幫助我編寫代碼。

也許您應該嘗試一些現有的JS Math庫,例如bignumber.js ,它支持任意精度算術。 從頭開始實施所有工作將非常耗時且乏味。

0.3+0.6    //0.8999999999999999
x = new BigNumber('0.3')    // "0.3"
y = new BigNumber('0.6')    // "0.6"
z = new BigNumber('0.9')    // "0.9"
z.equals(x.plus(y))    // true

我認為您應該將epsilon的價值提高一些。

您還可以看一下math.jsmath.js的比較函數還會檢查是否相等。 比較說明如下:

http://mathjs.org/docs/datatypes/numbers.html#comparison

因此,您可以執行以下操作:

math.equal(0.1 + 0.2, 0.3); // true
math.equal(0.3 + 0.6, 0.9); // true

更好的是,math.js支持bignumbers( 請參閱docs ),因此您可以執行以下操作:

math.equal(math.bignumber(0.1) + math.bignumber(0.2), math.bignumber(0.3);

或使用表達式解析器:

math.config({number: 'bignumber'});

math.eval('0.1 + 0.2');        // returns BigNumber 0.3, not 0.30000000000000004
math.eval('0.1 + 0.2 == 0.3'); // returns true

舍入錯誤會嚴重影響不連續的函數(例如相等性(也包括floor和ceil)),並且在某些情況下考慮到epsilon可能會起作用,但可能還會給出錯誤的答案(例如abs(xy) < eps可能在返回true時返回true x和y的確切值確實不同); 您應該進行錯誤分析以確保可以。 沒有通用的方法可以解決浮點問題:這取決於您的應用程序。 如果您輸入的是十進制數,而您僅使用加,減和乘,則十進制浮點算術可能是可以的,前提是精度足夠大,以便可以正確表示所有數據。 您還可以使用有理算術,例如大理性 (未嘗試)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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