admin管理员组

文章数量:1323714

Writing some test cases for my Javascript program that deals with binary and right now I'm just using stringify to check if the value and expected values are equal:

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

This works fine except for when I have floating point values. This is what happens:

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

Test Failed!

So I guess I can't use stringify anymore to check if my two objects/arrays are equal. What's a good way to check if two potentially deeply nested objects/arrays are equal while also taking in to account floating point values? That is, two floating point values should be considered equal if they are 99.99% the same or whatever.

Writing some test cases for my Javascript program that deals with binary and right now I'm just using stringify to check if the value and expected values are equal:

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

This works fine except for when I have floating point values. This is what happens:

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

Test Failed!

So I guess I can't use stringify anymore to check if my two objects/arrays are equal. What's a good way to check if two potentially deeply nested objects/arrays are equal while also taking in to account floating point values? That is, two floating point values should be considered equal if they are 99.99% the same or whatever.

Share Improve this question asked Jul 11, 2016 at 23:31 Chron BagChron Bag 5875 silver badges19 bronze badges 2
  • You need to write a recursive equivalence tester. And when it gets to a floating point number, it needs to pare them with tolerance, rather than ==. – Barmar Commented Jul 11, 2016 at 23:36
  • Comparing Objects using JSON.stringify is not a good idea as there is no guarantee of order, so two objects may have identical properties and values but evaluate to not "equal". You need to loop over the properties and values, there are many, many questions about that already. – RobG Commented Jul 12, 2016 at 0:30
Add a ment  | 

1 Answer 1

Reset to default 8

You'll need to test each element in the array in order, and you'll need to do it recursively for objects. This is typically known as a deep parison or deep equality. You should be able to do this using a recursive function that checks the type(s) of the parands.

When paring floating point values, you'll want to use a tolerance. You do this by taking the absolute value of subtracting the two numbers from each other, and then paring that to either a fixed tolerance value of your choosing, or a small number known as an epsilon.

In JavaScript, the machine epsilon is available as Number.EPSILON, and is defined to be the difference between 1 and the smallest number that is greater than 1 and can be represented as a Number. Similar constants are available in most languages and are typically used for tolerance-based parisons.

Tolerance-based parison turns floating point parisons from simple equality into a subtract and pare. If you'd normally write

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

you'd write that using the absolute value and a tolerance to eliminate floating point weirdness:

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

If the difference between a and b is smaller than tolerance, you treat them as equal.

For a more nuanced (but possibly overkill for your case) approach, see The Floating Point Guide's section on parison. The implementation presented there is in Java, but is likely portable to JavaScript without much effort.

本文标签: javascriptCheck if two objects are equal when they have floating point valuesStack Overflow