Javascript:精​​确奇怪的行为

时间:2012-05-12 09:15:01

标签: javascript jquery

  

可能重复:
  Is JavaScript's Math broken?

假设,

var x = .6 - .5;

var y = 10.2 – 10.1;

var z = .2  -  .1;

比较结果

x == y;     // false

x == .1;    // false

y == .1;    // false

z == .1;    // true

为什么Javascript会显示这种行为?

1 个答案:

答案 0 :(得分:6)

因为浮点不是很精确。您最终可能会遇到轻微的差异。

(旁注:我认为您的意思是var x = .6 - .5;否则,您要将-0.10.1进行比较。)

JavaScript使用IEEE-754双精度64位浮点(ref)。这是浮点数的非常好的近似值,但没有完美的方法来表示二进制中的所有浮点数。

有些差异比其他差异更容易看到。例如:

console.log(0.1 + 0.2); // "0.30000000000000004"

有一些JavaScript库可以执行“十进制”事件a'la C#的decimal类型或Java BigDecimal。这就是数字实际存储为一系列十进制数字的位置。但它们不是灵丹妙药,它们只是有一类不同的问题(例如,尝试用它来准确地表示1 / 3)。 “十进制”类型/库对于金融应用程序来说非常棒,因为我们习惯于处理财务方面所需的舍入方式,但是它们的成本往往比IEEE浮点要慢。

让我们输出您的xy值:

var x = .6 - .5;
console.log(x); // "0.09999999999999998"

var y = 10.2 - 10.1;
console.log(y); // "0.09999999999999964"

0.09999999999999998 !=0.09999999999999964并不奇怪。 : - )

您可以对这些进行合理化以使比较起作用:

function roundTwoPlaces(num) {
  return Math.round(num * 100) / 100;
}

var x = roundTwoPlaces(0.6 - 0.5);

var y = roundTwoPlaces(10.2 - 10.1);

console.log(x);       // "0.1"
console.log(y);       // "0.1"
console.log(x === y); // "true"

或更通用的解决方案:

function round(num, places) {
    var mult = Math.pow(10, places);
    return Math.round(num * mult) / mult;
}

Live example | source

请注意,如果在round具有相同位数的情况下运行,则至少两个非常非常非常接近的数字仍然可能存在于结果数中,最终应该是相同的数字(即使这个数字不完全准确)。