Nếu bạn sử dụng double
hoặc float
, bạn nên sử dụng làm tròn hoặc có thể thấy một số lỗi làm tròn. Nếu bạn không thể làm điều này, hãy sử dụng BigDecimal
.
Vấn đề bạn gặp phải là 0,1 không phải là một đại diện chính xác và bằng cách thực hiện phép tính hai lần, bạn đang cộng sai số đó.
Tuy nhiên, 100 có thể được biểu diễn chính xác, vì vậy hãy thử:
double x = 1234;
x /= 100;
System.out.println(x);
mà in:
12.34
Điều này hoạt động vì Double.toString(d)
thực hiện một số lượng nhỏ làm tròn thay mặt bạn, nhưng nó không nhiều. Nếu bạn đang tự hỏi nó sẽ trông như thế nào nếu không làm tròn:
System.out.println(new BigDecimal(0.1));
System.out.println(new BigDecimal(x));
bản in:
0.100000000000000005551115123125782702118158340454101562
12.339999999999999857891452847979962825775146484375
Tóm lại, việc làm tròn là không thể tránh khỏi đối với các câu trả lời hợp lý trong dấu phẩy động cho dù bạn có đang làm điều này một cách rõ ràng hay không.
Lưu ý: x / 100
và x * 0.01
không hoàn toàn giống nhau khi nói đến lỗi làm tròn. Điều này là do lỗi làm tròn đối với biểu thức đầu tiên phụ thuộc vào các giá trị của x, trong khi biểu thức 0.01
thứ hai có lỗi làm tròn cố định.
for(int i=0;i<200;i++) {
double d1 = (double) i / 100;
double d2 = i * 0.01;
if (d1 != d2)
System.out.println(d1 + " != "+d2);
}
bản in
0.35 != 0.35000000000000003
0.41 != 0.41000000000000003
0.47 != 0.47000000000000003
0.57 != 0.5700000000000001
0.69 != 0.6900000000000001
0.7 != 0.7000000000000001
0.82 != 0.8200000000000001
0.83 != 0.8300000000000001
0.94 != 0.9400000000000001
0.95 != 0.9500000000000001
1.13 != 1.1300000000000001
1.14 != 1.1400000000000001
1.15 != 1.1500000000000001
1.38 != 1.3800000000000001
1.39 != 1.3900000000000001
1.4 != 1.4000000000000001
1.63 != 1.6300000000000001
1.64 != 1.6400000000000001
1.65 != 1.6500000000000001
1.66 != 1.6600000000000001
1.88 != 1.8800000000000001
1.89 != 1.8900000000000001
1.9 != 1.9000000000000001
1.91 != 1.9100000000000001