Я возился с некоторым кодом C, используя числа с плавающей запятой, и получаю 1. # INF00, -1. # IND00 и -1. # IND, когда я пытаюсь напечатать числа с плавающей запятой на экране. Что означают эти значения?
Я считаю, что 1. # INF00 означает положительную бесконечность, но как насчет -1. # IND00 и -1. # IND? Я также иногда видел это значение: 1. $ NaN, которое не является числом, но что вызывает эти странные значения и как они могут помочь мне при отладке?
Я использую MinGW, который, как мне кажется, использует представление IEEE 754 для чисел с плавающей запятой.
Может ли кто-нибудь перечислить все эти недопустимые значения и их значение?





От Исключения с плавающей запятой IEEE в 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.
Я знаю, что OP на самом деле не просил об этом, но в качестве удобного теста myfloat == myfloat вернет false, если у вас есть одно из этих магических значений.
@tenpn На самом деле в C++ + infinity == + infinity. Попробуйте проверить 1.0 / 0.0: 1.#INF00 == 1.#INF00 возвращает истину, -1.#INF00 == -1.#INF00 возвращает истину, а 1.#INF00 == -1.#INF00 - ложь.
Не уверен в других конфигурациях, но в Windows 7 / Visual studio 2010. float nan = sqrtf (-1.0f); нан == нан; // оценивается как истина ... вопреки тому, что сказал tenpn .. (Комментарий Евгения V)
Если вы можете использовать C++ 11, посмотрите std :: isfinite () и тому подобное. Если вы можете использовать Boost, вы также повезло
@Jeff, скорее всего, связано с оптимизацией. См. соответствующая страница документации.
Для тех из вас, кто работает в среде .NET, следующее может быть удобным способом отфильтровать нечисловые значения (этот пример находится в VB.NET, но, вероятно, он похож на C#):
If Double.IsNaN(MyVariableName) Then
MyVariableName = 0 ' Or whatever you want to do here to "correct" the situation
End If
Если вы попытаетесь использовать переменную со значением NaN, вы получите следующую ошибку:
Value was either too large or too small for a Decimal.
Это не определяет 1.#INF. Вам также необходимо использовать Double.IsInfinity(MyVariableName) для проверки на +/- бесконечность.
На ваш вопрос "что это такое" уже дан ответ выше.
Что касается отладки (ваш второй вопрос), а также при разработке библиотек, где вы хотите проверять специальные входные значения, вы можете найти следующие функции, полезные в Windows C++:
_isnan (), _isfinite () и _fpclass ()
В Linux / Unix вы должны найти полезными isnan (), isfinite (), isnormal (), isinf (), fpclassify () (и вам может потребоваться связать с libm с помощью флага компилятора -lm).
Для тех, кто задается вопросом о разнице между -1.#IND00 и -1.#IND (о чем конкретно задан вопрос, и ни один из ответов не касается):
-1.#IND00
Это, в частности, означает ненулевое число, деленное на ноль, например 3.14 / 0 (источник)
-1.#IND (синоним NaN)
Это означает одно из четырех (см. вики из источник):
1) sqrt или log отрицательного числа
2) операции, в которых обе переменные равны 0 или бесконечности, например. 0 / 0
3) операции, в которых хотя бы одна переменная уже является NaN, например NaN * 5
4) триггер вне допустимого диапазона, например arcsin(2)
Именно так библиотека времени выполнения Microsoft C форматирует значения с плавающей запятой Infinity и NaN. MinGW не имеет собственного CRT, он использует поставляемую ОС msvcrt.dll. То, как это выглядит, зависит от спецификатора формата printf (), который вы использовали, поэтому от дополнительных нулей он может даже превратиться в 1. # J. Стандарт C99 устанавливает ожидаемый результат, принятый в VS2015, поэтому эта странность исчезнет.