GithubHelp home page GithubHelp logo

Comments (8)

sf105 avatar sf105 commented on July 20, 2024

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.

npryce avatar npryce commented on July 20, 2024

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.

brundegj avatar brundegj commented on July 20, 2024

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.

offbyone avatar offbyone commented on July 20, 2024

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.

brundegj avatar brundegj commented on July 20, 2024

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.

npryce avatar npryce commented on July 20, 2024

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.

brundegj avatar brundegj commented on July 20, 2024

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.

scarytom avatar scarytom commented on July 20, 2024

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)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.