3

I am trying to understand the behavior of the code below which I wrote to experiment on calculation overflow.

public static void main(String[] args) {

    System.out.println(getSomeValue());
    System.out.println(getFixedSomeValue());
}

private static double getSomeValue() {
    return (2500000 - 0) * 250000 * (200 + 310);
}

private static double getFixedSomeValue() {
    return (double) (2500000 - 0) * 250000 * (200 + 310);
}

output:

-9.9787264E8
3.1875E14

What I have understood is: It can be because of Integer overflow as:

Double.MAX_VALUE = 1.7976931348623157E308
Integer.MAX_VALUE = 2147483647

I don't understand why the values differ? When the return type of method is double, shouldn't it automatically cast it to double?

impossible
  • 2,380
  • 8
  • 36
  • 60
  • http://www.cs.bilkent.edu.tr/~guvenir/courses/CS101/op_precedence.html – Hermann Döppes Jun 11 '18 at 07:16
  • In the first case, you are doing only integer arithmetic. – Andy Turner Jun 11 '18 at 07:17
  • `getSomeValue` only use `int` so this will be integer operation giving integer result. I tried to give a complete answer in [Why is the result of 1/3 == 0?](https://stackoverflow.com/a/41822430/4391450) on how those operation worked.. – AxelH Jun 11 '18 at 07:17

3 Answers3

8

(2500000 - 0) * 250000 * (200 + 310) is an expression comprised of int literal and numeric operators, so it is evaluated using integer operators and the result is an int, and therefore overflows (since it is limited to Integer.MAX_VALUE). The overflown result is converted to double before the method returns, but that's too late.

When you add (double) at the beginning, you cast (2500000 - 0) to double and avoid the numeric overflow, since now all the operators are floating point operators that result in double value. This is similar to writing

return (2500000.0 - 0) * 250000 * (200 + 310)
               ^ decimal point = double literal rather than int
Michael
  • 41,989
  • 11
  • 82
  • 128
Eran
  • 387,369
  • 54
  • 702
  • 768
  • Thanks Eran! Just one more doubt, Am I safe doing a double cast as in getFixedSomeValue()? Or there is a better way to do that? – impossible Jun 11 '18 at 08:22
  • @impossible what do you mean by "safe"? If you mean to ask whether that code is safe to avoid numeric overflow, it is safe as long as the expression you case to `double` - (2500000 - 0) - doesn't overflow. I prefer to work with double literals, such as 2500000.0, instead of casting. – Eran Jun 11 '18 at 08:26
  • I am sorry to skip details. There are no literals but 'int' variables. But result I expect is in double. I just want to know, which one is safe: `(double) ((intA - intB) * (intC * intD * intE) * (intX + intY)); (double) ((double)(intA - intB) * (double)(intC * intD * intE) * (double)(intX + intY));` – impossible Jun 11 '18 at 08:52
  • 1
    @impossible the safest would be to change all the int variables to double. If that's not possible, cast the first operand in each expression to double. For example, if `intC * intD * intE` may result in int overflow, change it to `(double)intC * intD * intE`. Or, for the full expression - `((double)intA - intB) * ((double)intC * intD * intE) * ((double)intX + intY)` – Eran Jun 11 '18 at 08:57
  • I got my answer Eran! Thank you! – impossible Jun 11 '18 at 09:15
0

Yes and no. Upon return it casts it to double but the calculations are done in integer format which upon reaching the max value it starts from the min value again. So if you do INT_MAX + 1 you will get INT_MIN and that is why you are getting a negative result in double.

Ankit Kathait
  • 105
  • 1
  • 12
0

When the return type of method is double, shouldn't it automatically cast it to double?

It does, just not perhaps where you mean.

private static double getSomeValue() {
    return (2500000 - 0) * 250000 * (200 + 310);
}

is the same as:

private static double getSomeValue() {
    int e = (2500000 - 0) * 250000 * (200 + 310);
    return (double) e;
}

i.e. the expression is evaluated using int, and then cast to double at the very end.

Andy Turner
  • 137,514
  • 11
  • 162
  • 243
  • Thanks Andy, I got my answer for that question. Here is another. Are both of these same? 1. `(double) ((intA - intB) * (intC * intD * intE) * (intX + intY));` 2. `(double) ((double)(intA - intB) * (double)(intC * intD * intE) * (double)(intX + intY));` Can no 1 overflow on Integer? – impossible Jun 11 '18 at 08:54
  • "Here is another" If you have a separate question, please ask a separate question. – Andy Turner Jun 11 '18 at 09:21
  • Sorry, My bad. I should have not written like that. Actually both the questions are related. I got the 2nd question after I read your answer and got more understanding. – impossible Jun 11 '18 at 09:33