Question

I thought that MIN_NORMAL was a value that you could add to a "normal" double and the number will change. E.g. add Double.MIN_NORMAL to 0.1d and you get a value different from 0.1d, however my understanding is wrong:

public static void test(double val) {
    if (val == (val - Double.MIN_NORMAL*1e50d))
        System.out.printf("val == (val - Double.MIN_NORMAL*1e50d) for val=%.20f\n", val);
    else
        System.out.printf("val != (val - Double.MIN_NORMAL*1e50d) for val=%.20f\n", val);
}

Which produces:

test(0.0d);
> val != (val - Double.MIN_NORMAL*1e50d) for val=0.00000000000000000000

test(1.0d);
> val == (val - Double.MIN_NORMAL*1e50d) for val=1.00000000000000000000

test(0.1d);
> val == (val - Double.MIN_NORMAL*1e50d) for val=0.10000000000000000000

Somebody pls explain what's going against my logic here, that even if I add MIN_NORMAL times 1e50d, I still get the same number.

I checked binary representations and 1 * Double.MIN_NORMAL is different from 2 * Double.MIN_NORMAL, but subtracting those from anything except zero does not change the original number.

Was it helpful?

Solution

MIN_NORMAL is, as the Javadoc says, only the smallest normalized double value. But that doesn't mean it is something like 1 for ints: For floating-point point values, there simply is no standard "eps" you can add to change to the next representable value -- the "eps" always depends on the exponent of the given floating-point value. That's why they're called floating points, in the end :)

However, Java 1.6+ provides Math.nextAfter() which returns, for any given double, the next or previous representable double.

On older Java versions, you can always mess around with Double.doubleToLongBits(), incrementing or decrementing its result, and converting back by Double.longBitsToDouble(); this gets you the next or previous representable double value -- in most cases: there are a few special cases (NaN, infinite values), so this is not recommended to floating-point newbies :)

OTHER TIPS

Double has a limited precision. MIN_NORMAL is 2e-1022. It will be dropped unless the number you add it to is also in the ballpark of 2e-1000.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top