Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

cast from double to int is not always just dropping decimal part

Tags:

java

I'm experimenting with the code I found here The Java Specialists' Newsletter.

public class MeaningOfLife {
  public static String findOutWhatLifeIsAllAbout() {
  int meaning = 0;
  for (int i = 0; i < 10; i++) {
    for (int j = 0; j < 20; j++) {
      for (int k = 0; k < 300; k++) {
        for (int m = 0; m < 7000; m++) {
          meaning += Math.random() + 1;
        }
      }
    }
  }
  return String.valueOf(meaning).replaceAll("0*$", "");
  }

public static void main(String[] args) {
  System.out.println(findOutWhatLifeIsAllAbout());
}
}

The answer to the question "what does it print" seemed obvious once I realized that there is an implicit cast with the compound assignment operator +=.

But it printed something like: 420000006 or 420000007, instead of (the expected) 420000000 (or "42", after removing trailing zeros).

So that was showing that casting from double to int is not always just dropping the decimal part of the double as stated here: How to cast a double to an int in Java?

So I made some trials and here is an example of what I found:

System.out.println((int)  (131070.99999999999)); // -> 131070
System.out.println((int)  (131071.99999999999)); // -> 131071
System.out.println((int)  (131072.99999999999)); // -> 131073 !!!
System.out.println((int)  (131073.99999999999)); // -> 131074 !!!


System.out.println((int)  (16382.999999999999)); // -> 16382
System.out.println((int)  (16383.999999999999)); // -> 16383
System.out.println((int)  (16384.999999999999)); // -> 16385 !!!
System.out.println((int)  (16385.999999999999)); // -> 16386 !!!

...So now I'm looking for an explanation for that behavior ???

like image 463
pgras Avatar asked Dec 06 '11 16:12

pgras


People also ask

Does casting double to int round up or down?

It does not round, it just returns the integral part before the decimal point.

Does int () always round down?

Notes. INT is not equivalent to ROUNDDOWN with places set to 0 . INT rounds down using value, whereas ROUNDDOWN rounds down using absolute value, which causes differences for negative values of value . INT is also not equivalent to FLOOR with significance -1 for negative values of value for the same reason as above.

How do I restrict double to two decimal places?

We can use DecimalFormat("0.00") to ensure the number always round to 2 decimal places.

How does Casting a double to an int work?

double to int - Math.It accepts a double value and converts into the nearest long value by adding 0.5 and truncating decimal points. Once you got the long value, you can cast it to int again, as shown below: int a = (int) Math.


1 Answers

Many decimal values are not possible double values. Before they can be used they first have to be squeezed to whatever double value is closest.

Example: 16384.999999999999 has no exact double representation. The two closest values are 16384.99999999999636202119290828704833984375 and 16385.0. Squeezing down results in a difference of about 0.000000000003, while squeezing up results in a difference of 0.000000000001 - going up results in a closer value, so that's what it's interpreted as.

like image 134
Toomai Avatar answered Sep 22 '22 17:09

Toomai