JavaScript: 比较两个浮点数值

33

我有一个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<12.00的结果是false

有任何想法为什么会这样吗?

5个回答

43

toFixed 返回一个字符串,你正在比较两个结果字符串。按字典顺序,12 中的 1 出现在 7 之前,所以 12 < 7。

我想你想要比较类似于:

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

四舍五入保留两位小数


2
保留两位小数并保持数字不变:Math.round(parseFloat(cfVal)*100)/100 - Tomalak
这个回答对OP的问题很有帮助。然而,对于在Javascript中比较接近的浮点值来说并不是很有用,这需要精度值或者将其乘以某些十的倍数以移动到整数表示。此外,还有一个问题,那就是Javascript是否真正支持整数。 - Teddy

26

比较带有精度的浮点数:

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);

1
您能否解释一下当某个数字精确时意味着什么,以及为什么您建议采用相对误差方法?我已经谷歌搜索了一段时间,但是我无法理解您的意思或在这种情况下采用该方法的好处。非常感谢! - mahonya
2
@mahonya 相对误差不取决于两个值的大小,例如1001和1000。绝对误差为1,相对误差为0.001。有时候我们知道精确值,需要计算近似值。 - Edward
十进制比较是一种与语言无关的问题。指定“精度”是在某些情况下可行的解决方案,但值得注意的是它的局限性:当用于实现传递等价关系时可能会失败,即(n1-n2)<precision(n2-n3)<precision成立,但这并不意味着(n1-n3)<precision讨论 - MTV
这并未回答楼主的问题。楼主正在比较两个字符串。 - ggorlen

6

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

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

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

换句话说,您建议在两侧引入相同的错误,以使它们可以进行比较? - Teddy

3

使用短符号比较浮点数,也可以接受字符串和整数形式的浮点数:

var floatOne = 2, floatTwo = '1.456';

Math.floor(floatOne*100) > Math.floor(floatTwo*100) 

(!) 注意:比较使用整数。实际上发生的事情是: 200 > 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));


2
比较浮点数值是棘手的,因为存储在内存中的浮点值有一个长的“小数点”尾巴。最简单(实际上也是最好的)方法是:将值相乘,以减少已知数量的小数点位数为零,然后四舍五入该值(以摆脱尾巴)。
显然,比较的两个值必须乘以相同的比率。
例如: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)) ....

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接