2011-12-20 23 views
7

Tôi biết rất nguy hiểm khi kiểm tra phao cho sự bình đẳng do lỗi chính xác nhưng có an toàn để kiểm tra không? Tôi có thể nghĩ đến một số trường hợp, ví dụ như trong việc tối ưu hóa các trường hợp đặc biệt trong các thuật toán, nơi bạn sẽ muốn làm điều này. Câu hỏi liên quan đến phao nổi nhưng tôi cho rằng câu trả lời cũng được áp dụng để tăng gấp đôi.Có an toàn để kiểm tra phao cho 0.0 bình đẳng không?

Xét đoạn mã sau:

float factor = calculateFactor(); 
if(factor != 0.0f) 
    applyComplexAlgorithm(factor); 
+0

Tôi không chấp nhận câu trả lời chỉ vì lợi ích của việc có câu trả lời được chấp nhận trong câu hỏi của tôi, có thực sự là một câu trả lời mà tôi tìm thấy câu trả lời câu hỏi đầy đủ. –

Trả lời

8

Nó là an toàn theo nghĩa là nếu giá trị được thiết lập một cách rõ ràng để 0.0f, nó sẽ trở lại đúng đó.

KHÔNG an toàn theo nghĩa là bạn không nên mong đợi rằng kết quả giá trị từ các phép tính sẽ chính xác là 0,0f.

Vì vậy, bạn thực sự đang sử dụng 0.0f làm giá trị ma thuật đặc biệt, không phải là so sánh thực với 0.

+0

Phải, đó là một ví dụ xấu. Trong trường hợp này, những gì tôi thực sự có nghĩa là sử dụng 0,0f như một giá trị đặc biệt để so sánh với, một cái gì đó mà sẽ được thiết lập một cách rõ ràng. Tôi không biết tại sao tôi lại đưa ra ví dụ này vì nó thậm chí không phải là những gì tôi đang cố gắng làm. –

+0

Đã hiểu. Tuy nhiên, tránh các giá trị ma thuật rắc vào với các giá trị "thông thường". Chúng làm tổn thương khả năng phát hiện (như trong khi bạn nhìn vào chữ ký của hàm, không rõ ràng nó đang nói cho bạn điều gì khác ngoài yếu tố) và cũng làm cho nó liên quan nhiều hơn khi thử nghiệm (và sử dụng!) API. Thay vào đó, hãy thử cấu trúc lại để điều kiện này được hiển thị dưới dạng một API khác hoặc ít nhất là điều hiển nhiên trong cuộc gọi API (lệnh sau không hữu ích). – supermem613

5

Không, nó không phải là an toàn, bởi vì việc tính toán trong calculateFactor() có thể sẽ không dẫn đến 0,0 thậm chí thông qua đó số học nên. Một ví dụ nhỏ: (0,4-0,1) -0.3 khi thực hiện bằng double kết quả trong 5.551115123125783e-17

3

Đó chắc chắn an toàn, nhưng bạn phải xem xét ý nghĩa của nó đối với các thuật toán của bạn. Nếu thuật toán của bạn sử dụng factor làm số chia (và không tự kiểm tra chia cho số không), thì có, hoàn toàn hợp lý để kiểm tra factor != 0.0f trước khi gọi số applyComplexAlgorithm(factor).

Bây giờ, bạn có nên kiểm tra giá trị nhỏ hơn một số epsilon trước khi sử dụng factor hay không, hoàn toàn phụ thuộc vào mã của bạn và không thể được xác định riêng biệt với mã bạn đã cung cấp.

Nếu bạn đã sử dụng giá trị đặc biệt 0.0f dưới dạng giá trị nội dung cụ thể (chẳng hạn như không thể tính toán hệ số), thì có, hoàn toàn an toàn để so sánh việc sử dụng ==. Ví dụ, đoạn code sau của sử dụng 0.0f là xác định và không bao giờ phụ thuộc vào bất kỳ loại lỗi roundoff:

float calculateFactor() 
{ 
    int phase = moon_phase(); 
    if (phase == FULL) { // whatever special case requires returning 0.0f 
     return 0.0f; 
    } else { 
     return 1.0 + (phase * phase); // something that is never 0.0f 
    } 
} 

float factor = calculateFactor(); 
if(factor != 0.0f) 
    applyComplexAlgorithm(factor); 
Các vấn đề liên quan