2008-12-07 200 views
55

Tôi đang rối tung xung quanh với một số mã C bằng cách sử dụng phao nổi, và tôi nhận được 1. # INF00, -1. # IND00 và -1. # IND khi tôi cố gắng in nổi trên màn hình. Những giá trị đó có ý nghĩa gì?Điều gì làm 1. # INF00, -1. # IND00 và -1 # IND có nghĩa là gì?

Tôi tin rằng 1. # INF00 có nghĩa là vô cùng dương, nhưng khoảng -1. # IND00 và -1. # IND? Tôi cũng thấy đôi khi giá trị này: 1. $ NaN mà không phải là một số, nhưng những gì gây ra những giá trị lạ và làm thế nào những người có thể giúp tôi gỡ lỗi?

Tôi đang sử dụng MinGW mà tôi tin rằng sử dụng biểu thị IEEE 754 cho số điểm phao.

Ai đó có thể liệt kê tất cả các giá trị không hợp lệ đó và ý nghĩa của chúng không?

Trả lời

61

Từ IEEE floating-point exceptions in C++:

This page will answer the following questions.

  • My program just printed out 1.#IND or 1.#INF (on Windows) or nan or inf (on Linux). What happened?
  • How can I tell if a number is really a number and not a NaN or an infinity?
  • How can I find out more details at runtime about kinds of NaNs and infinities?
  • Do you have any sample code to show how this works?
  • Where can I learn more?

These questions have to do with floating point exceptions. If you get some strange non-numeric output where you're expecting a number, you've either exceeded the finite limits of floating point arithmetic or you've asked for some result that is undefined. To keep things simple, I'll stick to working with the double floating point type. Similar remarks hold for float types.

Debugging 1.#IND, 1.#INF, nan, and inf

If your operation would generate a larger positive number than could be stored in a double, the operation will return 1.#INF on Windows or inf on Linux. Similarly your code will return -1.#INF or -inf if the result would be a negative number too large to store in a double. Dividing a positive number by zero produces a positive infinity and dividing a negative number by zero produces a negative infinity. Example code at the end of this page will demonstrate some operations that produce infinities.

Some operations don't make mathematical sense, such as taking the square root of a negative number. (Yes, this operation makes sense in the context of complex numbers, but a double represents a real number and so there is no double to represent the result.) The same is true for logarithms of negative numbers. Both sqrt(-1.0) and log(-1.0) would return a NaN, the generic term for a "number" that is "not a number". Windows displays a NaN as -1.#IND ("IND" for "indeterminate") while Linux displays nan. Other operations that would return a NaN include 0/0, 0*∞, and ∞/∞. See the sample code below for examples.

In short, if you get 1.#INF or inf, look for overflow or division by zero. If you get 1.#IND or nan, look for illegal operations. Maybe you simply have a bug. If it's more subtle and you have something that is difficult to compute, see Avoiding Overflow, Underflow, and Loss of Precision. That article gives tricks for computing results that have intermediate steps overflow if computed directly.

+3

Tôi biết OP không thực sự yêu cầu điều này, nhưng như là một thử nghiệm tiện dụng, 'myfloat == myfloat' sẽ trả về false nếu bạn có một trong các giá trị ma thuật này. – tenpn

+7

@tenpn Trên thực tế trong C++, + vô cực == + vô cùng. Thử kiểm tra 1.0/0.0: '1. # INF00' ==' 1. # INF00' trả về giá trị true, '-1. # INF00' ==' -1. # INF00' trả về true, nhưng '1. # INF00' = = '-1. # INF00' là sai. – bobobobo

+2

Không chắc chắn về các cấu hình khác, nhưng trên Windows 7/Visual studio 2010. float nan = sqrtf (-1.0f); nan == nan; // đánh giá thành true ... trái với những gì tenpn đã nói .. (Comment by Yevgen V) – Jeff

3

Đối với những người bạn trong một môi trường .NET sau đây có thể là một cách tiện dụng để lọc không số ra (ví dụ này là trong VB.NET, nhưng đây có thể tương tự như trong C#):

If Double.IsNaN(MyVariableName) Then 
    MyVariableName = 0 ' Or whatever you want to do here to "correct" the situation 
End If 

Nếu bạn cố gắng sử dụng một biến mà có một giá trị NaN bạn sẽ nhận được lỗi sau:

Value was either too large or too small for a Decimal.

+3

Điều này không phát hiện được '1. # INF'. Bạn cũng cần sử dụng 'Double.IsInfinity (MyVariableName)' để kiểm tra +/- vô cùng. – user1318499

2

Câu hỏi của bạn "chúng là gì" đã được trả lời ở trên.

Theo như gỡ lỗi (câu hỏi thứ hai của bạn) mặc dù, và trong việc xây dựng thư viện mà bạn muốn kiểm tra cho các giá trị đầu vào đặc biệt, bạn có thể tìm thấy các chức năng sau hữu ích trong Windows C++:

_isnan(), _isfinite (), và _fpclass()

Trên Linux/Unix bạn nên tìm isnan(), isfinite(), isnormal(), isinf(), fpclassify() hữu ích (và bạn có thể cần liên kết với libm bằng cách sử dụng trình biên dịch cờ -lm).

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