0

I have the following try block to detect Integer overflow.

    try {

        Math.addExact((number % 10) * (int) Math.pow(10, i), reversedNumber);

    } catch(ArithmeticException ae) {

        return 0;

    }

Okay, so if i run the above code as is, it causes an ArithmeticException as expected. However, if I want to assign the result of addExact to an integer variable, the over flow is never detected.

    try {

        reversedNumber = Math.addExact((number % 10) * (int) Math.pow(10, i), reversedNumber);

    } catch(ArithmeticException ae) {

        return 0;

    }

Can someone tell me why the exception isn't caught upon assignment to a variable? Is it because the assignment process is itself successful so no exception is thrown?

public static int reverse(int x) {

    int number = Math.abs(x);
    if(number == 0) return number;

    int numberOfDigits = (int) Math.log10(number) + 1;
    
    int reversedNumber = 0;
    for(int i = numberOfDigits - 1; i >= 0; i--) {

        try {

            reversedNumber = Math.addExact((number % 10) * (int) Math.pow(10, i), reversedNumber);

        } catch(ArithmeticException ae) {

            return 0;

        }


        number /= 10;

    }

    return x < 0 ? -reversedNumber : reversedNumber;

}

with an input of 1534236469 the answer should be 0.

Mutating Algorithm
  • 2,604
  • 2
  • 29
  • 66
  • 2
    Can you show a [mcve]? Specifically, what are the values of `number`, `i` and `reversedNumber`? – Sweeper Jun 29 '20 at 03:07
  • @Sweeper https://ideone.com/AvFAqN it should return 0 – Mutating Algorithm Jun 29 '20 at 03:11
  • 1
    Please [edit] the [mcve] into your question, rather than including an external link. – Sweeper Jun 29 '20 at 03:12
  • 0 is a legitimate output. Perhaps you should return -1 on an exception so that you can be sure the exception was thrown? Or some other very unlikely number. Or perhaps put a print statement so that the exception being thrown is visible to you. – NomadMaker Jun 29 '20 at 03:23
  • @NomadMaker those are all undesirable, IMO. Better to throw another exception or return Optional.empty(). – Brian McCutchon Jun 29 '20 at 03:28
  • I'm just thinking for debugging purposes. Once the reason is known, then the better flows should be allowed. I'd just return an Integer or null, but I'm an old-time programmer. When I was young, we didn't even have negative numbers, let along these new-fangled Optiontionals. :) – NomadMaker Jun 29 '20 at 03:33

1 Answers1

3

It's not about whether you assign it to a variable or not. Your method correctly returns 0 for the input 1534236469 for the wrong reason, if you don't assign it to reversedNumber. For 1534236469, addExact does not throw an exception either way.

The addition is not overflowing, which is why addExact does not throw an exception. But the multiplication of (number % 10) * (int) Math.pow(10, i) is overflowing. In the first iteration of the loop, you are multiplying 9 * 1000000, which is out of the range of int.

addExact only checks the overflow of the addition of the two arguments you pass to it. It does not check the overflow during the evaluation of the two arguments themselves.

You need to use multiplyExact:

int powerOf10 = (int) Math.pow(10, i);
int digit = (number % 10);
reversedNumber = Math.addExact(Math.multiplyExact(digit, powerOf10), reversedNumber);]
Sweeper
  • 213,210
  • 22
  • 193
  • 313