2011-11-14 41 views
5

Trong C:tình trạng tương tự trong C và Java, kết quả khác nhau

float a = 1.3; 
if (a == 1.3) 
    printf("Hello c"); 
else 
    printf("Bye c"); 

//output: Bye c 

Trong Java:

float a = 1.3; 
if (a == 1.3) 
    System.out.println("Hello java"); 
else 
    System.out.println("Bye java"); 

//output: Hello java 

Tại sao điều này như vậy?

+2

I ' đã thực hiện một số [sửa lỗi nhỏ] (http://programmers.stackexchange.com/posts/119596/revisions) trong mã của bạn, không có cách nào mã ban đầu của bạn hoạt động. Bạn đã thấy mã của bạn tạo ra đầu ra hay bạn vừa chép nó từ đâu đó? – yannis

Trả lời

21

Bạn không thể đại diện chính xác "1.3" làm phao nhị phân.

Việc chuyển đổi từ chữ 1.3 sang phao sẽ dẫn đến một số dấu phẩy động gần bằng nhưng không chính xác bằng 1,3.

Trong trường hợp Java, bạn đã gặp may mắn vì JVM diễn giải "1.3" dưới dạng float java chuẩn và chuyển đổi thành cùng mức gần 1.3. Số nhị phân. Trong trường hợp C, tiêu chuẩn nói 1.3 nên được hiểu là "gấp đôi" và chuyển đổi nó thành một điểm nổi nhị phân gần hơn một chút so với giá trị thập phân 1.3 so với giá trị thông thường.

Điểm mấu chốt là bạn không bao giờ nên so sánh nổi cho bình đẳng như các biến thể nhỏ trong lưu trữ, thứ tự tính toán, vv sẽ tạo ra kết quả hơi khác nhau. Bạn nên luôn "gắn" bất kỳ so sánh nổi nào như vậy:

if (a > 1.299 && a < 1.301) // something close to 1.3 
+7

Chỉ cần là một nit-pick hoàn chỉnh: trong C, '1.3' luôn luôn là một đôi. Cú pháp của các ký tự float (độ chính xác đơn) là '1.3f'. – tdammers

+0

@tdammmers - cảm ơn. Tôi đã không chắc chắn cho dù đây là trình biên dịch cụ thể hoặc bắt buộc theo tiêu chuẩn. –

1

Chỉ để giúp bạn quấn bộ não xung quanh câu trả lời, hãy để tôi cho bạn một sự tương tự đơn giản. Hãy nhớ rằng các số dấu phẩy động là gần đúng. Nhiều số không thể được biểu diễn chính xác. Bây giờ, hãy tưởng tượng chúng ta làm điều tương tự với số thập phân, nói rằng chúng ta sử dụng sáu chữ số sau dấu thập phân.

Làm cách nào để biểu thị 1/3? .333333 là điều tốt nhất chúng ta có thể làm. Nhưng bây giờ 3 * 1/3 sẽ không bằng 1.

Làm thế nào để chúng tôi đại diện cho 2/3? .666666 ít nhất sẽ đảm bảo 2 * 1/3 = 2/3. Nhưng 2/3 + 1/3 sẽ không bằng 1.

Chúng tôi có thể đại diện 2/3 là .666667. Nhưng sau đó 2 * 1/3 sẽ không bằng 2/3. Nhưng ít nhất 1/3 + 2/3 sẽ bằng một.

Vì vậy, vấn đề là, với biểu diễn gần đúng, bạn không thể đảm bảo câu trả lời chính xác đúng, chỉ đóng đủ câu trả lời. Nói chung, bạn không bao giờ nên so sánh các số dấu chấm động cho sự bình đẳng trừ khi bạn là 100% tích cực bạn hiểu những gì bạn đang làm và tại sao.

0

Điều đầu tiên phải được biết đến với C là nó là rất sai để kiểm tra 2 số điểm nổi cho bình đẳng vì việc thực hiện các số dấu chấm động của trình biên dịch. '1.3' khi lưu trữ trong một biến nổi, bạn chưa điền vào tất cả các vị trí thập phân mà trình biên dịch lưu trữ và có khả năng sẽ được lấp đầy bằng một số chữ số, do đó làm cho sự thất bại đối với thử nghiệm bình đẳng

Các vấn đề liên quan