The issue is in the output formatting, specifically how doubles are converted to strings by default. Each double number has an exact value, but it is also the result of string to double conversion for a range of decimal fractions. In this case, the exact value of the double is -1350825904190559999913623552, but the range is [-1350825904190560137352577024,-1350825904190559862474670080].
The Double toString conversion picks the number from that range with the fewest significant digits, -1.35082590419056E27. That string does convert back to the original value.
If you really want to see the exact value, not just enough digits to uniquely identify the double, your current BigDecimal approach works well.
Here is the program I used to calculate the numbers in this answer:
import java.math.BigDecimal;
public class Test {
public static void main(String args[]) {
double value = -1350825904190559999913623552.00;
/* Get an exact printout of the double by conversion to BigDecimal
* followed by BigDecimal output. Both those operations are exact.
*/
BigDecimal bdValue = new BigDecimal(value);
System.out.println("Exact value: " + bdValue);
/* Determine whether the range is open or closed. The half way
* points round to even, so they are included in the range for a number
* with an even significand, but not for one with an odd significand.
*/
boolean isEven = (Double.doubleToLongBits(value) & 1) == 0;
/* Find the lower bound of the range, by taking the mean, in
* BigDecimal arithmetic for exactness, of the value and the next
* exactly representable value in the negative infinity direction.
*/
BigDecimal nextDown = new BigDecimal(Math.nextAfter(value,
Double.NEGATIVE_INFINITY));
BigDecimal lowerBound = bdValue.add(nextDown).divide(BigDecimal.valueOf(2));
/* Similarly, find the upper bound of the range by going in the
* positive infinity direction.
*/
BigDecimal nextUp = new BigDecimal(Math.nextAfter(value,
Double.POSITIVE_INFINITY));
BigDecimal upperBound = bdValue.add(nextUp).divide(BigDecimal.valueOf(2));
/* Output the range, with [] if closed, () if open.*/
System.out.println("Range: " + (isEven ? "[" : "(") + lowerBound + ","
+ upperBound + (isEven ? "]" : ")"));
/* Output the result of applying Double's toString to the value.*/
String valueString = Double.toString(value);
System.out.println("toString result: " + valueString);
/* And use BigDecimal as above to print the exact value of the result
* of converting the toString result back again.
*/
System.out.println("exact value of toString result as double: "
+ new BigDecimal(Double.parseDouble(valueString)));
}
}
Output:
Exact value: -1350825904190559999913623552
Range: [-1350825904190560137352577024,-1350825904190559862474670080]
toString result: -1.35082590419056E27
exact value of toString result as double: -1350825904190559999913623552