approx and deepApprox to safely compare numbers
Testing equallity of numbers is a tricky business because of possible round of errors in floating point numbers. For example the following test will unexpectedly fail as the result of the left expression is 0.22000000000000003 and not 0.22.
test.equal(2.2 / 10, 0.22);
It would be great to have functions like approx and deepApprox to safely compare numbers and objects/arrays containing numbers against each other. The function should compare whether the difference between the two numbers is at least a predefined factor epsilon smaller than the values itself (I guess there will be some edge cases when one of the values is zero, NaN, or Inf).
I second this. I think this is really important.
Today I tried to have a crack at writing this, but I didn't get anywhere because I can't figure out how to build this library. make build fails on a fresh clone.
What should the exact behaviour be when comparing near zero?
If we just test that the first n significant figures match, then that causes troubles near zero.
e.g. I think approx(1e-16,0) should pass.
But what about if both numbers are close to zero, but not exactly zero?
e.g. approx(1e-16,-1e-16). Should that pass? They're both approximately zero, but the difference between them is 100%.
There are different strategies.
The simplest strategy is calculating the absolute difference.
nearlyEqual = Math.abs(a - b) < EPSILON
where:
-
EPSILONis the absolute difference between x and y.
Another common strategy is looking at the relative difference, which allows comparing values very close to zero too:
diff = Math.abs(x - y)
nearlyEqual = (diff <= Math.max(Math.abs(x), Math.abs(y)) * EPSILON) OR (diff < DBL_EPSILON)
where:
-
EPSILONis the relative difference between x and y. -
DBL_EPSILONis the minimum positive floating point number such that1.0 + DBL_EPSILON != 1.0. This is a constant with a value of approximately2.2204460492503130808472633361816e-16