0

I have been asked a question in Interview which was related to Integer overflow. The question was simple but I could not find a an easy solution to count the result of overflowed value.

For Example, Following program should print 1000 as output but it prints 5 due the Integer overflow.

public class IntegerOvewflow {

    /**
     * Java does not have target typing, a language feature wherein the type of the
     * variable in which a result is to be stored influences the type of the
     * computation.
     * 
     * @param args
     */
    public static void main(String[] args) {
        final long MICROS_PER_DAY = 24 * 60 * 60 * 1000 * 1000;
        final long MILLIS_PER_DAY = 24 * 60 * 60 * 1000;
        System.out.println(MICROS_PER_DAY / MILLIS_PER_DAY);

    }
}

But, here can we use any specific formula or equation to calculate the output of overflowed value. Here the number is really big and not easy to judge the output quickly by human mind.

Gunjan Shah
  • 5,088
  • 16
  • 53
  • 72
  • 1
    isn't it just about adding `L` to the number literals like `24L * 60L * 60L * 1000L * 1000L`? – m.antkowicz May 09 '19 at 18:53
  • 1
    even one long number would be enough I guess. – Michał Krzywański May 09 '19 at 18:55
  • @michalk yup you're right – m.antkowicz May 09 '19 at 19:00
  • Puzzle 3 from this book https://doc.lagout.org/programmation/Java/Java%20Puzzlers_%20Traps%2C%20Pitfalls%2C%20and%20Corner%20Cases%20%5BBloch%20%26%20Gafter%202005-07-04%5D.pdf , i used to ask many questions at interview from this book , when i was doing technical recruiting for my previous companies – Yugansh May 09 '19 at 20:48
  • Thank you all for the suggestions. Here, I am aware of the answer to add L to the number but my question is more focused to know the outcome of overflowed value. Here, the number is big and I can not guess what will be value of MICROS_PER_DAY after integer overflow. So want to know if any mathematical equation present to find solution of such puzzles. – Gunjan Shah May 10 '19 at 02:43
  • Thank you Yugansh. This PDF is awesome.. – Gunjan Shah May 10 '19 at 02:47

3 Answers3

1

Specify that they are long with L, because if not you're doing int multiplication which results in an int which touch the overflow and then store into a long

public static void main(String[] args) {
    final long MICROS_PER_DAY = 24 * 60 * 60 * 1000 * 1000L;
    final long MILLIS_PER_DAY = 24 * 60 * 60 * 1000L;
    System.out.println(MICROS_PER_DAY / MILLIS_PER_DAY);   // 1000
}

Check out : https://ideone.com/5vHjnH

azro
  • 53,056
  • 7
  • 34
  • 70
1

This is the classic Problem from the very good book , Java Puzzlers Link to Book

Puzzle 3: Long Division This puzzle is called Long Division because it concerns a program that divides two long values. The dividend represents the number of microseconds in a day; the divisor, the number of milliseconds in a day. What does the program print?

public class LongDivision {
public static void main(String[] args) {
final long MICROS_PER_DAY = 24 * 60 * 60 * 1000 * 1000;
final long MILLIS_PER_DAY = 24 * 60 * 60 * 1000;
System.out.println(MICROS_PER_DAY / MILLIS_PER_DAY);
}

}

Solution 3: Long Division This puzzle seems reasonably straightforward. The number of milliseconds per day and the number of microseconds per day are constants. For clarity, they are expressed as products. The number of microseconds per day is (24 hours/day · 60 minutes/hour · 60 seconds/minute · 1,000 milliseconds/second · 1,000 microseconds/millisecond).

The number of milliseconds per day differs only in that it is missing the final factor of 1,000. When you divide the number of microseconds per day by the number of milliseconds per day, all the factors in the divisor cancel out, and you are left with 1,000, which is the number of microseconds per millisecond. Both the divisor and the dividend are of type long, which is easily large enough to hold either product without overflow.

It seems, then, that the program must print 1000. Unfortunately, it prints 5. What exactly is going on here? The problem is that the computation of the constant MICROS_PER_DAY does overflow. Although the result of the computation fits in a long with room to spare, it doesn’t fit in an int. The computation is performed entirely in int arithmetic, and only after the computation completes is the result promoted to a long. By then, it’s too late: The computation has already overflowed, returning a value that is too low by a factor of 200. The promotion from int to long is a widening primitive conversion [JLS 5.1.2], which preserves the (incorrect) numerical value. This value is then divided by MILLIS_PER_DAY, which was computed correctly because it does fit in an int. The result of this division is 5. So why is the computation performed in int arithmetic? Because all the factors that are multiplied together are int values. When you multiply two int values, you get another int value. Java does not have target typing, a language feature wherein the type of the variable in which a result is to be stored influences the type of the computation. It’s easy to fix the program by using a long literal in place of an int as the first factor in each product. This forces all subsequent computations in the expression to be done with long arithmetic. Although it is necessary to do this only in the expression for MICROS_PER_DAY, it is good form to do it in both products. Similarly, it isn’t always necessary to use a long as the first value in a product, but it is good form to do so. Beginning both computations with long values makes it clear that they won’t overflow.

This program prints 1000 as expected:

public class LongDivision {
public static void main(String[] args) {
final long MICROS_PER_DAY = 24L * 60 * 60 * 1000 * 1000;
final long MILLIS_PER_DAY = 24L * 60 * 60 * 1000;
System.out.println(MICROS_PER_DAY / MILLIS_PER_DAY);
}
}

The lesson is simple: When working with large numbers, watch out for overflow—it’s a silent killer. Just because a variable is large enough to hold a result doesn’t mean that the computation leading to the result is of the correct type. When in doubt, perform the entire computation using long arithmetic. The lesson for language designers is that it may be worth reducing the likelihood of silent overflow. This could be done by providing support for arithmetic that does not overflow silently. Programs could throw an exception instead of overflowing, as does Ada, or they could switch to a larger internal representation automatically as required to avoid overflow, as does Lisp. Both of these approaches may have performance penalties associated with them. Another way to reduce the likelihood of silent overflow is to support target typing, but this adds significant complexity to the type system [Modula-3 1.4.8].

Yugansh
  • 365
  • 3
  • 9
  • Thanks for details explanation. But. I want to know how can we judge answer of such puzzle. If I will face similar question in interview then how can I calculate the result. Can we use any mathematical equation or function ? – Gunjan Shah May 10 '19 at 02:58
  • For that you need to know about the overflow , this holds true for all other primitives deal if , long result = a operation b; if ( (a < 0 && b < 0 && r >= 0) || (a > 0 && b > 0 && r <= 0) ) { // Overflow occurred , as in case of overflow results will flip so you can detect the overflow using this } – Yugansh May 10 '19 at 04:47
  • bool isOverflow(long long a, long long b) { // Check if either of them is zero if (a == 0 || b == 0) return false; long long result = a * b; if (a == result / b) return false; else return true; } For Multiply and Divide – Yugansh May 10 '19 at 04:54
0

You can use BigInteger class for exactly these purposes.

Oracle documentation: here

There is a good quick article in this link

kpark
  • 394
  • 2
  • 12
  • does not make sense - take a look, the variable is already `long` not the `int` – m.antkowicz May 09 '19 at 18:58
  • @m.antkowicz BigInteger has a maximum limit of `(2 ^ 32) ^ Integer.MAX_VALUE`. `BigInteger` class is dealt with using `int[]` [here](https://stackoverflow.com/questions/12693273/is-there-an-upper-bound-to-biginteger). I would say `BigInteger` is probably not the most elegant solution since it would require some rewrites to the code but it was to ensure calculations are made despite how large the numbers are as OP implies. – kpark May 09 '19 at 20:06
  • the problem is not on the left side of the statement but on the right ;) – m.antkowicz May 09 '19 at 20:16
  • True. I dunno what I was looking at but for some reason, I thought he was working on a problem and the above was just a sample. Makes a lot of sense that this was an interview question and he was simply looking for a solution to the problem xD – kpark May 09 '19 at 20:34