Редактировать
Я стою исправлено Эндрю.Спасибо!
Java следует IEEE 754 с основанием 2, поэтому он не может правильно представить 0,1 (это приблизительно. 0.1000000000000000055511151231257827021181583404541015625
или 1.1001100110011001100110011001100110011001100110011010 * 2^-4
в IEEE), которое вы можете узнать на основе двоичного представлениядвойного типа (бит 63
= знак, биты 62-52
= экспонента и биты 51-0
- мантисса):
long l = Double.doubleToLongBits(0.1);
System.out.println(Long.toBinaryString(l));
Я просто увлекся результатами и подумал омомент, когда поплавки в Java работают с основанием 10, и в этом случае можно было бы просто представить 0.1 просто отлично.
А теперь, надеюсь, раз и навсегда прояснить ситуацию, вот что происходит:
BigDecimal bigDecimal1 = new BigDecimal(0.1d);
BigDecimal bigDecimal2 = new BigDecimal(1.1d - 1.0);
BigDecimal bigDecimal3 = new BigDecimal(1.1d);
BigDecimal bigDecimal4 = new BigDecimal(1.0d);
System.out.println(bigDecimal1.doubleValue());
System.out.println(bigDecimal2.doubleValue());
System.out.println(bigDecimal3.doubleValue());
System.out.println(bigDecimal4.doubleValue());
System.out.println(bigDecimal1);
System.out.println(bigDecimal2);
System.out.println(bigDecimal3);
System.out.println(bigDecimal4);
Выходы:
0.1
0.10000000000000009
1.1
1.0
0.1000000000000000055511151231257827021181583404541015625
0.100000000000000088817841970012523233890533447265625
1.100000000000000088817841970012523233890533447265625
1
Так что же происходит?1.1 - 1.0 эквивалентно:
1.100000000000000088817841970012523233890533447265625 - 1
(Java не может точно представить 1.1), что равно 0.100000000000000088817841970012523233890533447265625
, и это отличается от способа, которым Java представляет 0.1 внутри (0.1000000000000000055511151231257827021181583404541015625
)
ЕслиВы задаетесь вопросом, почему результат вычитания отображается как 0.10000000000000009
, а "0.1" отображается как есть, посмотрите здесь