What's wrong with using == to compare floats in Java?

后端 未结 21 1710
你的背包
你的背包 2020-11-22 01:00

According to this java.sun page == is the equality comparison operator for floating point numbers in Java.

However, when I type this code:



        
相关标签:
21条回答
  • 2020-11-22 01:16

    The following automatically uses the best precision:

    /**
     * Compare to floats for (almost) equality. Will check whether they are
     * at most 5 ULP apart.
     */
    public static boolean isFloatingEqual(float v1, float v2) {
        if (v1 == v2)
            return true;
        float absoluteDifference = Math.abs(v1 - v2);
        float maxUlp = Math.max(Math.ulp(v1), Math.ulp(v2));
        return absoluteDifference < 5 * maxUlp;
    }
    

    Of course, you might choose more or less than 5 ULPs (‘unit in the last place’).

    If you’re into the Apache Commons library, the Precision class has compareTo() and equals() with both epsilon and ULP.

    0 讨论(0)
  • 2020-11-22 01:18

    This is a problem not specific to java. Using == to compare two floats/doubles/any decimal type number can potentially cause problems because of the way they are stored. A single-precision float (as per IEEE standard 754) has 32 bits, distributed as follows:

    1 bit - Sign (0 = positive, 1 = negative)
    8 bits - Exponent (a special (bias-127) representation of the x in 2^x)
    23 bits - Mantisa. The actuall number that is stored.

    The mantisa is what causes the problem. It's kinda like scientific notation, only the number in base 2 (binary) looks like 1.110011 x 2^5 or something similar. But in binary, the first 1 is always a 1 (except for the representation of 0)

    Therefore, to save a bit of memory space (pun intended), IEEE deccided that the 1 should be assumed. For example, a mantisa of 1011 really is 1.1011.

    This can cause some issues with comparison, esspecially with 0 since 0 cannot possibly be represented exactly in a float. This is the main reason the == is discouraged, in addition to the floating point math issues described by other answers.

    Java has a unique problem in that the language is universal across many different platforms, each of which could have it's own unique float format. That makes it even more important to avoid ==.

    The proper way to compare two floats (not-language specific mind you) for equality is as follows:

    if(ABS(float1 - float2) < ACCEPTABLE_ERROR)
        //they are approximately equal
    

    where ACCEPTABLE_ERROR is #defined or some other constant equal to 0.000000001 or whatever precision is required, as Victor mentioned already.

    Some languages have this functionality or this constant built in, but generally this is a good habit to be in.

    0 讨论(0)
  • 2020-11-22 01:18

    If you *have to* use floats, strictfp keyword may be useful.

    http://en.wikipedia.org/wiki/strictfp

    0 讨论(0)
  • 2020-11-22 01:18

    Are you dealing with outsourced code that would use floats for things named sectionID and currentSectionID? Just curious.

    @Bill K: "The binary representation of a float is kind of annoying." How so? How would you do it better? There are certain numbers that cannot be represented in any base properly, because they never end. Pi is a good example. You can only approximate it. If you have a better solution, contact Intel.

    0 讨论(0)
  • 2020-11-22 01:20

    What is wrong with using == to compare floating point values?

    Because it's not true that 0.1 + 0.2 == 0.3

    0 讨论(0)
  • 2020-11-22 01:20

    In one line answer I can say, you should use:

    Float.floatToIntBits(sectionID) == Float.floatToIntBits(currentSectionID)
    

    To make you learned more about using related operators correctly, I am elaborating some cases here: Generally, there are three ways to test strings in Java. You can use ==, .equals (), or Objects.equals ().

    How are they different? == tests for the reference quality in strings meaning finding out whether the two objects are the same. On the other hand, .equals () tests whether the two strings are of equal value logically. Finally, Objects.equals () tests for any nulls in the two strings then determine whether to call .equals ().

    Ideal operator to use

    Well this has been subject to lots of debates because each of the three operators have their unique set of strengths and weaknesses. Example, == is often a preferred option when comparing object reference, but there are cases where it may seem to compare string values as well.

    However, what you get is a falls value because Java creates an illusion that you are comparing values but in the real sense you are not. Consider the two cases below:

    Case 1:

    String a="Test";
    String b="Test";
    if(a==b) ===> true
    

    Case 2:

    String nullString1 = null;
    String nullString2 = null;
    //evaluates to true
    nullString1 == nullString2;
    //throws an exception
    nullString1.equals(nullString2);
    

    So, it’s way better to use each operator when testing the specific attribute it’s designed for. But in almost all cases, Objects.equals () is a more universal operator thus experience web developers opt for it.

    Here you can get more details: http://fluentthemes.com/use-compare-strings-java/

    0 讨论(0)
提交回复
热议问题