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.
MIN_NORMAL
is, as the Javadoc says, only the smallest normalized double
value. But that doesn't mean it is something like 1
for int
s: 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 :)