Javascript:精确奇怪的行为

Javascript:精确奇怪的行为,javascript,jquery,Javascript,Jquery,可能重复: 假设 var x = .6 - .5; var y = 10.2 – 10.1; var z = .2 - .1; 比较结果 x == y; // false x == .1; // false y == .1; // false 但是 为什么Javascript会显示这样的行为?因为浮点不是完全精确的。最终可能会有细微的差异 (旁注:我认为您的意思是var x=.6-.5;否则,您将-0.1与0.1进行比较) JavaScript使用双精度64

可能重复:

假设

var x = .6 - .5;

var y = 10.2 – 10.1;

var z = .2  -  .1;
比较结果

x == y;     // false

x == .1;    // false

y == .1;    // false
但是


为什么Javascript会显示这样的行为?

因为浮点不是完全精确的。最终可能会有细微的差异

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

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

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

console.log(0.1 + 0.2); // "0.30000000000000004"
有一些JavaScript库实现了“十进制”功能,如C#的
decimal
类型或Java的
BigDecimal
。这就是数字实际存储为一系列十进制数字的地方。但它们不是万灵药,它们只是有一类不同的问题(例如,尝试用它准确地表示
1/3
)。“Decimal”类型/库对于金融应用程序来说是非常棒的,因为我们习惯于处理金融数据中所需的舍入方式,但它们往往比IEEE浮点运算速度慢

让我们输出您的
x
y
值:

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

var y = 10.2 - 10.1;
console.log(y); // "0.09999999999999964"
0.09999999998
,这并不奇怪=
0.09999999964
:-)

您可以将这些合理化一点,以便进行比较:

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


请注意,精度crud仍有可能出现在结果数字中,但如果以相同的位数在
轮中运行,则至少有两个非常、非常、非常接近的数字应该是相同的数字(即使该数字并非完全准确)因为浮点不是完全精确的。最终可能会有细微的差异

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

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

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

console.log(0.1 + 0.2); // "0.30000000000000004"
有一些JavaScript库实现了“十进制”功能,如C#的
decimal
类型或Java的
BigDecimal
。这就是数字实际存储为一系列十进制数字的地方。但它们不是万灵药,它们只是有一类不同的问题(例如,尝试用它准确地表示
1/3
)。“Decimal”类型/库对于金融应用程序来说是非常棒的,因为我们习惯于处理金融数据中所需的舍入方式,但它们往往比IEEE浮点运算速度慢

让我们输出您的
x
y
值:

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

var y = 10.2 - 10.1;
console.log(y); // "0.09999999999999964"
0.09999999998
,这并不奇怪=
0.09999999964
:-)

您可以将这些合理化一点,以便进行比较:

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


请注意,精度crud仍有可能出现在结果数字中,但如果以相同的位数在
轮中运行,则至少有两个非常、非常、非常接近的数字应该是相同的数字(即使该数字并非完全准确).

你的前两次比较有点奇怪。你为什么希望他们能匹配?(-0.1 vs 0.1)相关:前两次比较有点奇怪。你为什么希望他们能匹配?(-0.1 vs 0.1)相关:永远不要指望JavaScript的浮点数精度…=)@本克斯:恩,这对大多数目的来说都足够好了。记住,这不仅仅是JavaScript;很多系统都使用IEEE-754,这是一个非常聪明的把戏。你在那里做的最后一个把戏很有趣,伙计!我的意思是,无论标准JS使用什么,这都是疯狂的如果你不介意的话,我会保存这个解决方案。这是否适用于较小的数字,如:0.00245?@benqus:是的,我添加了一个更通用的解决方案。当然,不能保证除以100(或其他)不会在结果中产生类似的令人尴尬的积垢。但至少如果你输入了两个彼此非常非常接近的数字,它们(理论上)应该得出相同的值(即使该值不是非常精确)。千万不要指望JavaScript的浮点数精度…=)@本克斯:恩,这对大多数目的来说都足够好了。记住,这不仅仅是JavaScript;很多系统都使用IEEE-754,这是一个非常聪明的把戏。你在那里做的最后一个把戏很有趣,伙计!我的意思是,无论标准JS使用什么,这都是疯狂的如果你不介意的话,我会保存这个解决方案。这是否适用于较小的数字,如:0.00245?@benqus:是的,我添加了一个更通用的解决方案。当然,不能保证除以100(或其他)不会在结果中产生类似的令人尴尬的积垢。但至少如果你输入两个彼此非常非常接近的数字,它们(理论上)应该都有相同的值(即使这个值不是非常精确)。