-
-
Notifications
You must be signed in to change notification settings - Fork 696
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add almostEqual which does epsilon comparison for floating point rounding errors. #89
Comments
I think you will find what you are looking for in the chai-stats plugin. I just updated it to ensure compatibility with the 1.1.x chai release. It uses a precision indicator to indicate the decimal places. More info on how it is used is in the readme. assert.almostEqual(a, b, 2); |
Thanks for fast response. I looked on the chai-stats and in my opinion it's not that good choice. Here's why I think so:
function functionToBeTested() {
return (new Date().getTime());
}
function test() {
var a = functionToBeTested();
assert.ok(Math.abs(a - (new Date().getTime()) < 50); // Make sure that the timestamp is close enough to current time.
// or with my suggestion:
// assert.almostEqual(a, (new Date().getTime()), 50);
} This example is not suitable if the epsilon is simplified into the 'decimal' arguments.
It's also useful to link into this article: http://floating-point-gui.de/ |
We actually already have this, now that I think about it... https://github.com/chaijs/chai/blob/master/lib/chai/core/assertions.js#L1027-1047 But... we don't have an assert equivalent. I can add that in. |
If anybody comes across this from Google like I did, I wrote a function for this, see this gist: assert-close-enough. I probably didn't follow the chai api correctly, but it works for me. Edit: I misread the request, but the gist I wrote might be useful. It automatically determines epsilon, so you don't have to worry about the scale of the numbers you are comparing. |
@Klortho Chai offers a // expect interface
expect(1000.43 - 1000.0).to.be.approximately(0.43, 0.000001);
expect(1000.43 - 1000.0).to.be.closeTo(0.43, 0.000001);
// assert interface
assert.closeTo(1000.43 - 1000.0, 0.43, 0.000001); |
Well, What's needed (still, IMO) is a comparison with the correct scale. Your example works fine if the developer knows ahead of time the values to expect. But if those are computed, and at some completely different order of magnitude, it could easily fail. For example: it('should work for every SI prefix', function() {
[ 'micro', 'milli', 'kilo', 'mega', ...].forEach(function(prefix) {
const size = unitUnderTest.size(prefix);
assert.closeTo(size, lookup(prefix), 0.000001);
});
}); That's pretty contrived, but the point is that there's no reason the developer should have to even think about or guess. We know what the precision is of JS numbers, and can calculate what is "close enough" from the input values. |
@Klortho Gotcha. If this is something you think should be in Chai core, please open a new issue. This one is nearly 4 years old, and (despite the title) the OP was asking for something a little different than you are. In particular, they wanted the ability to specify the allowed delta. Their first example is the one I borrowed from, and their second example required being able to provide a specific delta in milliseconds for their timestamp comparison, both of which are solved by the current |
Yes, you are right -- I read as far as "epsilon" and skimmed the rest. I do wish chai had this function, but if no one else has asked for it in all this time, I'll just keep using my local customization. Thanks! |
Why is this issue closed?? |
As javascript stores numbers as doubles inside, one should not just compare optimistically numbers with ==.
For example:
var a = 1000.43 - 1000.0;
var b = 0.43;
a is now 0.42999999999995 and b is 0.43 and thus a == b is false.
The correct (and standard way) to compare these is the epsilon comparison:
Math.abs(a - b) < epsilon, where epsilon is a sufficient small number like 0.000001
I propose a new almostEqual function:
function almostEqual(actual, expected, epsilon, [message]) which compares by comparing Math.abs(actual - expected) < epsilon.
The text was updated successfully, but these errors were encountered: