Analyzing the Java floating point equality

Analyzing the Java floating point equality

Problem is described as follows:
Given two variables double a, double b, their corresponding variables are the type of packing Double x, Double y, Q:

  1. If there is a group of a, b, x, y, meet a == b &&! X.equals (y)?
  2. If there is a group of a, b, x, y, meet a! = B && x.equals (y)?

At first glance it seems impossible, in fact, the existence of such a value, refer to the following codes

public static void main() {
    double a = 0.0;
    double b = -0.0;
    double c = Double.NaN;
    double d = Double.NaN;
    Double x = a;
    Double y = b;
    Double z = c;
    Double w = d;
    System.out.println(a == b);         //输出true
    System.out.println(x.equals(y));    //输出false
    System.out.println(c == d);         //输出false
    System.out.println(w.equals(z));    //输出true
}

Double type equalsimplement and method ==Operators Logical vary.
Look ==operator to Java8 example, according to the Java Language Specification 15.21.1 , for floating point equality tests, compliant IEEE 754 specification:

  1. As long as there is one operand is NaN, ==the result of the expression is always false, !=the result of the expression is always true. In fact, if and only if xthe value NaN, the expression x!=xis true. You can use Float.NaNa method or a Double.NaNmethod of determining whether a value NaN.
  2. Positive and negative 0 is equal to 0, for example, the expression 0.0==-0.0is true.
  3. In addition, the use of two different floating-point ==or !=when the operator determines equality, recognize that they are not equal. In particular, a positive value indicates infinity, a value representing negative infinity; if they are compared with themselves, are equal; compared with other values are not equal.

Look at the JDK Double equals method to achieve:

    public boolean equals(Object obj) {
        return (obj instanceof Double)
               && (doubleToLongBits(((Double)obj).value) ==
                      doubleToLongBits(value));
    }

    /**
     * Returns a representation of the specified floating-point value
     * according to the IEEE 754 floating-point "double
     * format" bit layout.
     *
     * <p>Bit 63 (the bit that is selected by the mask
     * {@code 0x8000000000000000L}) represents the sign of the
     * floating-point number. Bits
     * 62-52 (the bits that are selected by the mask
     * {@code 0x7ff0000000000000L}) represent the exponent. Bits 51-0
     * (the bits that are selected by the mask
     * {@code 0x000fffffffffffffL}) represent the significand
     * (sometimes called the mantissa) of the floating-point number.
     *
     * <p>If the argument is positive infinity, the result is
     * {@code 0x7ff0000000000000L}.
     *
     * <p>If the argument is negative infinity, the result is
     * {@code 0xfff0000000000000L}.
     *
     * <p>If the argument is NaN, the result is
     * {@code 0x7ff8000000000000L}.
     *
     * <p>In all cases, the result is a {@code long} integer that, when
     * given to the {@link #longBitsToDouble(long)} method, will produce a
     * floating-point value the same as the argument to
     * {@code doubleToLongBits} (except all NaN values are
     * collapsed to a single "canonical" NaN value).
     *
     * @param   value   a {@code double} precision floating-point number.
     * @return the bits that represent the floating-point number.
     */
    public static long doubleToLongBits(double value) {
        long result = doubleToRawLongBits(value);
        // Check for NaN based on values of bit fields, maximum
        // exponent and nonzero significand.
        if ( ((result & DoubleConsts.EXP_BIT_MASK) ==
              DoubleConsts.EXP_BIT_MASK) &&
             (result & DoubleConsts.SIGNIF_BIT_MASK) != 0L)
            result = 0x7ff8000000000000L;
        return result;
    }

Double equals method by ==the operator, determines two objects doubleToLongBits return value is equal to that if two objects are equal. There is a method comment

If the argument is NaN, the result is 0x7ff8000000000000L

Analyzing it using equals two NaN, the result is true.
In other cases, according to the binary value of said doubleToLongBitsreturn value corresponding long. And 0.0and -0.0different sign bit, the binary representation is different, doubleToLongBitsthe results are different.

Guess you like

Origin www.cnblogs.com/filozofio/p/12304424.html