4

According to the standard, overflow in java is handled using a special value called infinity, but here the sum is 3.4028235E38. Why is this the case?

public class FloatingPointTest {
    public static void main(String[] args) {
        float a = Float.MAX_VALUE;
        float b = 1_000_000_000f; // Note the 'f' to ensure it's a float literal
        float sum = a + b;

        System.out.println("Float.MAX_VALUE: " + a);
        System.out.println("Large number: " + b);
        System.out.println("Sum: " + sum);
        System.out.println("Is sum equal to Float.POSITIVE_INFINITY? " + (sum == Float.POSITIVE_INFINITY));
    }
}
4
  • 8
    For the same reason than 1 + 1e-30 == 1: b is so small compared to a that it gets rounded away. Commented Aug 17 at 13:41
  • 1
    Try doing the addition by hand using the IEEE 754 addition algorithm. Commented Aug 17 at 13:58
  • 1
    maybe be interesting to check the documentation of Math.ulp() --- or just add 2e31f to Float.MAX_VALUE instead of 1e9f Commented Aug 18 at 14:57
  • Related: Floating Point: Distance between MAX and INF. Commented Aug 19 at 9:46

2 Answers 2

5

Summary

An arithmetic result is rounded before it is tested for overflow. If the rounded result is representable, there is no overflow.

Details

For rounding, Java uses IEEE 754’s round-to-nearest, ties-to-even method (per The Java Virtual Machine Specification, JAVA SE 18 Edition 2022-02-23, clause 2.8 Floating-Point Arithmetic, page 20).

Rounding in IEEE-754 behaves as if the range were unbounded (per IEEE 754-2019 draft D2.47, clause 4.3, first paragraph, page 18). That is, the rounding is performed as if there were no bound on the exponent, and then a check for overflow is performed. For illustration, suppose we had a two-digit decimal format that had finite numbers up to, but not including, 100. So 99 is representable but 100 is out of bounds. Consider adding 99 and .23. The exact result would be 99.23. This is above 99, but we do not declare overflow yet. First, we round 99.23 to two digits. The result is 99. This is within the finite range, so it does not overflow.

In the binary32 format that Java uses for Float, Float.MAX_VALUE is 2128−2104. If the exponent were not bounded, the next greater representable value would be 2128. When we add 109 to Float.MAX_VALUE, the exact result would be 2128−2104+109. When we round, this is nearer to 2128−2104 than it is to 2128. So it is rounded to 2128−2104, and there is no overflow.

Discussion

The rule that we round before we test for overflow makes sense: There is no reason for rounding to change at the edge of the finite range or to produce an infinity when the ordinary result of rounding would be finite. If we changed the rules to make any result outside the finite range an overflow, then floating-point arithmetic would behave differently near the edge of the range than it does inside the finite range.

If you added 2103 to Float.MAX_VALUE, the exact result, 2128−2104+2103 would be exactly halfway between 2128−2104 and 2128. The rule for tied results is to round to the choice with the even low digit in its significand. The low digit of 2128−2104 is 1, and the low digit of 2128 is 0, so the result would be 2128. That is out of the finite range, so an overflow would be declared.

Sign up to request clarification or add additional context in comments.

1 Comment

It's well known that computing properly-rounded results typically requires the use of one or more guard digits for intermediate results. Your statements rounding in IEEE-754 behaves as if the range were unbounded and we round before we test for overflow make me realize: To get this right (but get it right easily and generally), an implementation just needs the equivalent of guard digits on intermediate exponents, too.
0

In Java, Float.MAX_VALUE is the largest finite representable float value (≈ 3.4028235e38).

But when you add a small value to it (like +1 or even +1000), it doesn’t change at all, because that extra value is too small compared to Float.MAX_VALUE — it’s lost due to limited precision of floating-point representation (IEEE 754).

Infinity is only reached when the result of an operation exceeds the largest representable float.

public class FloatMaxValue {
    public static void main(String[] args) {
        float max = Float.MAX_VALUE;
        
        System.out.println("Float.MAX_VALUE = " + max);

        float result1 = max + 1;
        System.out.println("Float.MAX_VALUE + 1 = " + result1);

        float result2 = max * 2;
        System.out.println("Float.MAX_VALUE * 2 = " + result2);

        float result3 = max + 1e30f; 
        System.out.println("Float.MAX_VALUE + 1e30f = " + result3);

        float result4 = max * 1.1f;  
        System.out.println("Float.MAX_VALUE * 1.1f = " + result4);
    }
}

Ans
Float.MAX_VALUE = 3.4028235E38

Float.MAX_VALUE + 1 = 3.4028235E38 // No change

Float.MAX_VALUE * 2 = Infinity // Overflows to Infinity

Float.MAX_VALUE + 1e30f = 3.4028235E38 // Still no change

Float.MAX_VALUE * 1.1f = Infinity // Overflows to Infinity

Float.MAX_VALUE + 1 → stays the same, because 1 is tiny compared to 1e38, so it cannot affect the float’s mantissa.

Only multiplying by a big enough number (e.g., *2, *1.1) makes it overflow, resulting in Infinity.

3 Comments

You've got a couple of misleading statements. Infinity is only reached when the result of an operation exceeds the largest representable float. No, it's when the value exceeds the largest representable float, and then some. Only multiplying by a big enough number makes it overflow No, there are numbers you can add. The smallest is 1.01412048e+31. See the answer at this question.
You’re right — thanks for pointing that out . I should clarify: 1.Infinity happens not just when you “exceed Float.MAX_VALUE” but when the computed value is beyond the largest representable finite float. That means some additions can indeed push it over the edge (not just multiplications). 2. For example, Float.MAX_VALUE + 1f won’t change (precision loss), but Float.MAX_VALUE + 1.01412048e31f does overflow to Infinity because that number is large enough to affect the exponent.
precise statement should be: a ) Adding very small numbers has no effect due to limited precision, b ) Adding sufficiently large numbers (like ~1e31) or multiplying by factors > 1 can push it into Infinity.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.