Đó là vì giá trị float gần nhất là 1,3 không giống giá trị kép gần nhất với 1,3. Giá trị sẽ không phải là chính xác 1.3 - không thể được biểu diễn chính xác trong biểu diễn nhị phân không lặp lại.
Để cung cấp một sự hiểu biết khác nhau về việc tại sao điều này xảy ra, giả sử chúng ta có hai chữ số thập phân loại dấu chấm động - decimal5
và decimal10
, nơi số lượng đại diện cho số chữ số có nghĩa. Bây giờ giả sử chúng tôi đã cố gắng gán giá trị "một phần ba" cho cả hai. Bạn sẽ kết thúc với
decimal5 oneThird = 0.33333
decimal10 oneThird = 0.3333333333
Rõ ràng các giá trị đó không bằng nhau. Đó chính là điều tương tự ở đây, chỉ với những căn cứ khác nhau liên quan.
Tuy nhiên nếu bạn hạn chế các giá trị để loại kém chính xác, bạn sẽ thấy họ là bằng trong trường hợp đặc biệt này:
double d = 1.3d;
float f = 1.3f;
System.out.println((float) d == f); // Prints true
Đó là không đảm bảo được các trường hợp, tuy nhiên. Đôi khi sự xấp xỉ từ chữ số thập phân đến biểu diễn kép, và sau đó tính xấp xỉ của giá trị đó với đại diện nổi, kết thúc là kém chính xác hơn so với số thập phân thẳng để xấp xỉ xấp xỉ. Một ví dụ về điều này 1.0000001788139343 (nhờ stephentyrone để tìm ví dụ này).
Somewaht an toàn hơn, bạn có thể làm việc so sánh giữa đôi, nhưng sử dụng một float
đen trong việc bố trí ban đầu:
double d = 1.3f;
float f = 1.3f;
System.out.println(d == f); // Prints true
Trong trường hợp sau, đó là một chút như nói rằng:
decimal10 oneThird = 0.3333300000
Tuy nhiên, như được chỉ ra trong các nhận xét, bạn gần như chắc chắn không nên được so sánh các giá trị dấu phẩy động với ==. Đó là gần như không bao giờ điều phải làm, bởi vì chính xác loại điều này. Thông thường, nếu bạn muốn so sánh hai giá trị bạn thực hiện với một số loại so sánh bình đẳng "mờ", kiểm tra xem hai số đó có "đủ gần" cho mục đích của bạn hay không. Xem trang Java Traps: double để biết thêm thông tin.
Nếu bạn thực sự cần kiểm tra tính bình đẳng tuyệt đối, thường cho biết bạn nên sử dụng định dạng số khác ở địa điểm đầu tiên - ví dụ, đối với dữ liệu tài chính, bạn nên sử dụng BigDecimal
.
Rất đẹp giải thích, mặc dù nó có thể cho một giá trị thập phân cẩn thận crafted để thất bại so sánh '((float) decimalValueAsDouble == decimalValueAsFloat)', do làm tròn đôi. –
@stephentyrone: Có, tôi nghi ngờ nó có thể là - mặc dù tôi chưa đưa ra bất kỳ ví dụ nào. –
Điều duy nhất làm tôi lo lắng với bài viết này là bằng cách nào đó nó cho OP ấn tượng rằng anh ấy có thể sử dụng và sử dụng == nếu anh ta không hiểu các bình luận. Một người khác đã đăng liên kết này: http://firstclassthoughts.co.uk/java/traps/java_double_traps.html giải thích điều này khá tốt. – Fredrik