jjj
jjj

Reputation: 2672

Overflow and Underflow in Java Float and Double Data Types

I have created the following code to test Float and Double Java numeric data types for underflow and overflow:

// Float Overflow & Underflow
float floatTest = Float.MAX_VALUE;
floatTest++;
out.println("Float Overflow: " + Float.MAX_VALUE + " + 1 = " + floatTest);
floatTest = Float.MIN_VALUE;
floatTest--;
out.println("Float Underflow: " + Float.MIN_VALUE + " - 1 = " + floatTest);
out.println("");

// Double Overflow & Underflow
double doubleTest = Double.MAX_VALUE;
doubleTest++;
out.println("Double Overflow: " + Double.MAX_VALUE + " + 1 = " + doubleTest);
doubleTest = Double.MIN_VALUE;
doubleTest--;
out.println("Double Underflow: " + Double.MIN_VALUE + " - 1 = " + doubleTest);
out.println("");

Can someone explain the weird values I see in the result: enter image description here

When I do the similar test (code below) with byte, short, int and long:

// BYTE Overflow & Underflow
byte byteTest = Byte.MAX_VALUE;
byteTest++;
out.println("Byte Overflow: " + Byte.MAX_VALUE + " + 1 = " + byteTest);
byteTest = Byte.MIN_VALUE;
byteTest--;
out.println("Byte Underflow: " + Byte.MIN_VALUE + " - 1 = " + byteTest);
out.println("");

// SHORT Overflow & Underflow
short shortTest = Short.MAX_VALUE;
shortTest++;
out.println("Short Overflow: " + Short.MAX_VALUE + " + 1 = " + shortTest);
shortTest = Short.MIN_VALUE;
shortTest--;
out.println("Short Underflow: " + Short.MIN_VALUE + " - 1 = " + shortTest);
out.println("");

// INTEGER Overflow & Underflow
int intTest = Integer.MAX_VALUE;
intTest++;
out.println("Integer Overflow: " + Integer.MAX_VALUE + " + 1 = " + intTest);
intTest = Integer.MIN_VALUE;
intTest--;
out.println("Integer Underflow: " + Integer.MIN_VALUE + " - 1 = " + intTest);
out.println("");

// LONG Overflow & Underflow
long longTest = Long.MAX_VALUE;
longTest++;
out.println("Long Overflow: " + Long.MAX_VALUE + " + 1 = " + longTest);
longTest = Long.MIN_VALUE;
longTest--;
out.println("Long Underflow: " + Long.MIN_VALUE + " - 1 = " + longTest);
out.println("");

The results look as expected:

enter image description here

Can someone explain overflow and underflow in Java float and double and why am I seeing above results?

Upvotes: 4

Views: 6248

Answers (3)

Hayden
Hayden

Reputation: 31

your results aren't necessarily out of the ordinary, it's just that floats in general are very specific and your request is very close. I have had similar problems while using double data types. Just double check to make sure that your code checks out with what you were expecting.

Upvotes: 0

korolar
korolar

Reputation: 1535

These "weird" results are not really specific to Java. It's just that floats as defined by the relevant IEEE standard, are much more complicated than most people suspect. But onto your specific results: Float.MIN_VALUE is the smallest positive float, so it's very close to 0. Hence Float.MIN_VALUE - 1 will be very close to -1. But since the float precision around -1 is greater than that difference, it comes out as -1. As to Float.MAX_VALUE, the float precision around this value is much greater than 1 and adding one doesn't change the result.

Upvotes: 5

rgettman
rgettman

Reputation: 178263

Floating Point Overflow

Adding 1 to Double.MAX_VALUE OR Float.MAX_VALUE doesn't represent enough of a value to avoid getting rounded down due to precision error. At Double.MAX_VALUE, the difference between consecutive values, due to there being 53 bits for mantissa, is quite large.

System.out.println("Math.ulp(Double.MAX_VALUE) is " + Math.ulp(Double.MAX_VALUE));

1.9958403095347198E292

This value is 2971.

You need to add an expression that yields at least this much to overflow to Infinity. I say "yields at least this much" because I can get this to overflow by adding 2970, but 2969 has no effect.

doubleTest += Math.pow(2.0, 969);

1.7976931348623157E308

And

doubleTest += Math.pow(2.0, 970);

Infinity

It looks like 2970 gets rounded up to 2971 to get added to Double.MAX_VALUE, but 2969 gets rounded down to 0 and has no effect on the sum.

A similar process is occurring for float, though the values aren't nearly so high.

Floating Point Underflow

doubleTest = Double.MIN_VALUE;
doubleTest--;

This is just an infinitesimal value minus one, which is practically minus one. This not underflow.

Underflow occurs when the exponent, not the value, gets too low to be represented, so 0.0 results. Divide by 2 instead to get underflow.

doubleTest = Double.MIN_VALUE;
doubleTest /= 2;

0.0

Integer/Long Overflow/Underflow

Those are the expected values because you know the values "wrap around" to the other side of the range of values.

Upvotes: 8

Related Questions