2016-07-11 73 views
1

写一些测试用例我的JavaScript程序二进制而现在我只是用字符串化交易,以检查是否值和预期值相等:检查两个对象是否具有浮点值时是否相等?

JSON.stringify(val) === JSON.stringify(expected) 

这个工程除了当我已经浮精点值。这是发生了什么:

Given Value: [10,20,30,32.400001525878906,{"test":3,"asdf":23}] 
Expected Value: [10,20,30,32.4,{"test":3,"asdf":23}] 

Test Failed! 

所以我想我不能使用字符串化了检查我的两个对象/数组相等。检查两个潜在深度嵌套的对象/数组是否相等,同时考虑浮点值又是什么方法?也就是说,如果两个浮点数值相同或不相等,则99.99%应视为相等。

+0

你需要写一个递归等价测试器。当它达到浮点数时,它需要将它们与容差进行比较,而不是'=='。 – Barmar

+0

使用JSON.stringify比较对象不是一个好主意,因为不能保证顺序,所以两个对象可能具有相同的属性和值,但评估为不“相等”。你需要遍历的属性和值,有[*许多,许多问题已经*](http://stackoverflow.com/search?q=%5Bjavascript%5D+compare+objects)。 – RobG

回答

1

您需要按顺序测试数组中的每个元素,并且您需要递归执行对象。这通常被称为深度比较或深度平等。您应该可以使用递归函数来检查比较对象的类型。

比较浮点值时,您需要使用容差。您可以通过将两个数值相互减去的绝对值进行比较,然后将其与您选择的固定容差值或称为ε的小数值进行比较。

在JavaScript中,机器最小可作为Number.EPSILON,并且被定义为1,而大于1 可以表示为一个Number最小数量之间的差。类似的常量在大多数语言中都可用,并且通常用于基于容差的比较。

基于容差的比较将浮点比较从简单的等式转换为减法和比较。如果你通常写

if (a === b) { ... } 

你会写,使用绝对值和tolerance消除浮点怪事:

var tolerance = Number.EPSILON; 
if (Math.abs(a - b) < tolerance) { ... } 

如果ab之间的差值小于tolerance小,你对待他们是平等的。

对于更细微的(但可能矫枉过正)的方法,请参阅The Floating Point Guide's section on comparison。这里介绍的实现是用Java编写的,但很可能不需要太多努力就可以使用JavaScript。

+0

我认为Number.EPSILON有点太小而无法使用。我认为它应该根据实际数量(或它们的差异)按比例缩放。因此,相当大的数字不会相差1.0p的ulp。 –

+0

是的,我试图在这里谈论这一点,但不一定是成功的。 :)打开如何更好地回答问题的建议。 –