There are several steps involved here, each with different numbers. Let's split the code up for each statement:
double original = 128.12301; // Or 128888.12301
float floatValue = (float) original;
double backToDouble = (double) floatValue;
System.out.println(backToDouble);
So for each number, the steps are:
- Compile time: Convert the decimal value in the source code into the nearest exact
double
value
- Execution time: Convert the
double
value to the nearest exact float
value
- Execution time: Convert the
float
value into a double
value (this never loses any information)
- Execution time: Convert the final
double
value into a string
Steps 1 and 2 can lose information; step 4 doesn't always print the exact value - it just follows what Double.toString(double)
does.
So let's take 128.12301 as an example. That's converted at compile-time to exactly 128.123009999999993624442140571773052215576171875. Then the conversion to float
yields exactly 128.123016357421875. So after the conversion back to double
(which preserves the value) we print out 128.123016357421875. That prints 128.12301635712188 because that's the fewest digits in can print out without being ambiguous between that value and the nearest double
value greater than or less than it.
Now with 128888.12301, the exact double
value is 128888.123009999995701946318149566650390625 - and the closest float
to that is exactly
128888.125. After converting that back to a double
, the exact value of that double
is printed out because there are other exact double
values near it.
Basically, the result will depend on how many significant digits you've included to start with, and how much information is lost when it rounds to the nearest double
and then to the nearest float
.