Comments (8)
Been thinking about this. In which situations would you come up with a value that's close to, but not equal to, +-infinity? In practice, shouldn't people use equalTo() since it's most likely to be a marker value?
Similarly, I don't see what number is close to NaN.
Perhaps there should be special matchers for these values?
from javahamcrest.
NaN can't be tested by equals. NaN is defined to not be equal to any floating point value, even NaN itself. So it needs a special matcher: isNaN or somesuch.
from javahamcrest.
Just got bit by this, and it certainly looks like a bug to me. Double.NaN should match Double.NaN (even if they aren't equal in the JVM). Same with Infinity.
The fix is trivial. Add these lines to top of the matchesSafely(Double item) method:
if (item == this.value) return true; // handles infinity
if (Double.isNaN(item) && Double.isNaN(value)) return true;
return actualDelta(item) <= 0.0;
I have a fix and test, so if you'd like a patch I'm happy to contribute.
from javahamcrest.
I'm not sure that's mathematically correct; asserting that NaN is equal to
NaN seems to me to be a risky proposition.
We'd probably want explicit isInfinity/isNaN matchers to be more correct.
On Mon, Nov 19, 2012 at 10:32 AM, brundegj [email protected] wrote:
Just got bit by this, and it certainly looks like a bug to me. Double.NaN
should match Double.NaN (even if they aren't equal in the JVM). Same with
Infinity.The fix is trivial. Add these lines to top of the matchesSafely(Double
item) method:
if (item == this.value) return true; // handles infinity
if (Double.isNaN(item) && Double.isNaN(value)) return true;
return actualDelta(item) <= 0.0;I have a fix and test, so if you'd like a patch I'm happy to contribute.
—
Reply to this email directly or view it on GitHubhttps://github.com//issues/7#issuecomment-10524965.
Chris R.
Not to be taken literally, internally, or seriously.
Twitter: http://twitter.com/offby1
from javahamcrest.
I don't think we are asserting that NaN equals NaN. We're asserting that if the expected value is NaN, and we get a NaN, that they match. As far as I'm aware matchers don't have to follow the definition of equals. After all, the name of the matcher is IsCloseTo (though for NaNs we would require an exact match, of course).
Furthermore, in the definition of Double.equals() NaN DOES equal NaN. This test passes:
assertThat(new Double(Double.NaN).equals(Double.NaN), is(true));
Hence my fix from the previous post was overly complicated. This implementation seems to work fine:
if (item.equals(value)) return true;
return actualDelta(item) <= 0.0;
The use case here is that I'm testing a statistical algorithm that may return NaN for some subset of its output. Hence it's hard to separate out these cases in the tests (this is an integration test, the unit tests are simpler). But logically it seems very straightforward:
Double[] inputs = {80, 40, 20, 10, 5, 2.5, 1.25, 0.625, 0.313, 0.156, 0.078};
Double[] expectedOutputs = {176122.8, NaN, 74702.1, 35242.8, 15491.8, 8189.1, 4123.0, 2043.8, 1064.6, 488.6, 240.4};
Adding extra code to check for NaNs and do the assert with a different match seems like unnecessary complexity. The intent is simple: that the actual output array matches the expected output array. I can't think of any usage scenario when it would be advantages for NaN to not match NaN (though maybe others can). It seems like the above case is the common case, and should be supported without extra coding.
from javahamcrest.
NaN is not close to NaN. NaN is not a number -- it's an "unknown thing" and, by definition, you cannot say if it is close or not to something else that is an "unknown thing".
In your specific use case, the change you're asking for will make your test code easier to write. But it will change the semantics of a published library API that is used by thousands of developers worldwide, without any change to the method signature, making it match more widely than it does at the moment. I think that's too risky. It would change test code to not detect errors that it currently detects, without warning.
Instead I think you should write a matcher in your project that expresses match that your use case requires. Something like:
Matcher<Double> isCloseEnoughTo(double expected, double delta) {
return Double.isNaN(expected) ? isNaN() : isCloseTo(expected, delta);
}
where isNaN() is a matcher that returns if a double value is NaN.
from javahamcrest.
Ok, that's exactly what I've already done (including the name :-).
I guess I had a hard time seeing what errors this would detect, since it will only affect matches that have NaN set as the expected value, and those matchers will never match any value given to them. I just can't think of why anyone would write code that does this. Nevertheless, there's millions of code structures out there that I wouldn't think of or expect, so I can't argue with the point that there are too many tests out there to change it now.
I'll be writing a custom matcher to handle this case. I wonder how many times this matcher has been written before. A new type of Double matcher that handles these cases might be a useful addition to the library.
from javahamcrest.
I've added a new type of Double matcher that specifically targets Double.NaN. This doesn't give you a matcher that matches either double values or NaN, but you can compose that as demonstrated in Nat's post.
Matcher<Double> isCloseEnoughTo(double expected, double delta) {
return Double.isNaN(expected) ? Matchers.notANumber() : Matchers.closeTo(expected, delta);
}
OK to close this issue now?
from javahamcrest.
Related Issues (20)
- containsInAnyOrder incorrectly identifies differences in identical collections HOT 1
- Hamcrest 3.0? HOT 2
- You should be able to specify a lambda to return a reason
- Conflicting license declarations HOT 1
- Not sure why assertThat() doesn't work in this case HOT 2
- 301 Moved Permanently
- assertThat(this.object, hasProperty("booleanName")) fails to match boolean types and renames the property HOT 1
- The matcher contains() is misleading HOT 2
- FR: Matching maps with various type HOT 1
- oss-fuzz integration
- Participitation in Hacktoberfest?
- HasProperty Matcher doesn't work with Java Records HOT 1
- assertThat(Int::class.java, typeCompatibleWith(Number::class.java)) in kotlin always fails
- hamcrest matching on actual empty list fails with nosuchmethoderror HOT 1
- Test output Alignment
- record version fails the hasProperty HOT 1
- has property fails with non public class.. not sure if this correct as per java standards of property
- Double "close-to" matcher that uses the ULP.
- GraalVM Native Image support HOT 3
- Inquiry about Project Activity and Future Plans HOT 13
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from javahamcrest.