【问题标题】:Javascript: Comparing two float valuesJavascript:比较两个浮点值
【发布时间】:2024-01-24 04:57:01
【问题描述】:

我有这个 JavaScript 函数:

Contrl.prototype.EvaluateStatement = function(acVal, cfVal) {

    var cv = parseFloat(cfVal).toFixed(2);
    var av = parseFloat(acVal).toFixed(2);

   if( av < cv) // do some thing
}

当我比较浮点数 av=7.00cv=12.00 时,7.00&lt;12.00 的结果是 false

有什么想法吗?

【问题讨论】:

  • 这让我发疯了,谢谢你的提问!

标签: javascript comparison floating-point numbers


【解决方案1】:

toFixed 返回一个字符串,您正在比较两个结果字符串。在词汇上,12 中的 1 出现在 7 之前,所以 12

我猜你想比较类似的东西:

(Math.round(parseFloat(acVal)*100)/100)

四舍五入到小数点后两位

【讨论】:

  • 四舍五入到小数点后两位:Math.round(parseFloat(cfVal)*100)/100
【解决方案2】:

比较浮点数和精度:

var precision = 0.001;

if (Math.abs(n1 - n2) <= precision) {
  // equal
}
else {
  // not equal
}

更新: 或者,如果其中一个数字是精确的,则将精度与相对误差进行比较

var absoluteError = (Math.abs(nApprox - nExact)),
  relativeError = absoluteError / nExact;

return (relativeError <= precision);

【讨论】:

  • 您是否有机会解释其中一个数字准确时的含义,以及为什么您建议使用相对误差方法?我用谷歌搜索了一段时间,但我无法理解您的意思或在这种情况下您的方法的好处。将不胜感激!
  • @mahonya 相对误差不取决于两个值的大小,例如 1001 和 1000。绝对误差为 1,相对误差为 0.001。有时确切的值是已知的并计算出近似值。
  • 感谢爱德华的澄清。
【解决方案3】:

Math.fround() 函数返回数字的最接近的 32 位单精度浮点表示。

因此是比较 2 个浮点数的最佳选择之一。

if (Math.fround(1.5) < Math.fround(1.6)) {
    console.log('yes')
} else {
    console.log('no')
}

>>> yes

// More examples:
console.log(Math.fround(0.9) < Math.fround(1));                            >>> true
console.log(Math.fround(1.5) < Math.fround(1.6));                          >>> true
console.log(Math.fround(0.005) < Math.fround(0.00006));                    >>> false
console.log(Math.fround(0.00000000009) < Math.fround(0.0000000000000009)); >>> false

【讨论】:

    【解决方案4】:

    使用短符号比较浮点数,也接受浮点数作为字符串和整数:

    var floatOne = 2, floatTwo = '1.456';
    
    Math.floor(floatOne*100) > Math.floor(floatTwo*100) 
    

    (!) 注意:使用整数进行比较。幕后实际发生了什么:200 &gt; 145

    用零扩展 100 以获得更高的小数精度。例如使用 1000 表示 3 位小数精度。

    测试:

    var floatOne = 2, floatTwo = '1.456';
    console.log(Math.floor(floatOne*100), '>', Math.floor(floatTwo*100), '=', Math.floor(floatOne*100) > Math.floor(floatTwo*100));

    【讨论】:

      【解决方案5】:

      浮点值的比较很棘手,因为存储在内存中的浮点值的“后点”尾部很长。最简单(实际上也是最好)的方法是:将值相乘,以将 已知 后点数字的数量减少为零,然后将值四舍五入(去除尾部)。

      显然,两个比较值必须乘以相同的比率。

      F.i.: 1,234 * 1000 得到 1234 - 可以很容易地比较。 5,67 可以乘以 100,以减少一般的浮点比较问题,但不能与第一个值(1,234 vel 1234)进行比较。所以在这个例子中,它需要乘以 1000。

      那么比较代码可能看起来像(在元代码中):

        var v1 = 1.234;
        var v2 = 5.67;
      
        if (Math.round(v1*1000) < Math.round(v2*1000)) ....
      

      【讨论】: