Что означают 1.#INF00, -1.#IND00 и -1. # IND?
Я возлюсь с кодом C, используя float, и получаю 1.#INF00, -1.#IND00 и -1. # IND, когда пытаюсь напечатать плавающие объекты на экране. Что означают эти значения?
Я считаю, что 1. # INF00 означает положительную бесконечность, но как насчет -1. # IND00 и -1.#IND? Я также иногда видел это значение: 1.$NaN, который не является числом, но что вызывает эти странные значения и как они могут помочь мне в отладке?
Я использую MinGW, который, я полагаю, использует представление IEEE 754 для чисел с плавающей точкой.
Может ли кто-нибудь перечислить все эти недопустимые значения и что они значат?
4 ответа
Из исключений IEEE с плавающей точкой в C++:
Эта страница ответит на следующие вопросы.
- Моя программа только что распечатала 1.#IND или 1.#INF (в Windows) или nan или inf (в Linux). Что случилось?
- Как я могу определить, является ли число действительно числом, а не NaN или бесконечностью?
- Как я могу узнать больше деталей во время выполнения о видах NaN и бесконечности?
- У вас есть пример кода, чтобы показать, как это работает?
- Где я могу узнать больше?
Эти вопросы связаны с исключениями с плавающей запятой. Если вы получаете какой-то странный нечисловой вывод, где вы ожидаете число, вы либо превысили конечные пределы арифметики с плавающей запятой, либо запросили какой-то неопределенный результат. Для простоты я остановлюсь на работе с двойным типом с плавающей точкой. Аналогичные замечания справедливы для типов с плавающей точкой.
Отладка 1.#IND, 1.#INF, nan и inf
Если ваша операция сгенерирует большее положительное число, чем может быть сохранено в double, операция вернет 1. # INF в Windows или inf в Linux. Точно так же ваш код вернет -1.#INF или -inf, если результатом будет отрицательное число, слишком большое, чтобы его можно было хранить в двойном размере. Деление положительного числа на ноль дает положительную бесконечность, а деление отрицательного числа на ноль - отрицательную бесконечность. Пример кода в конце этой страницы продемонстрирует некоторые операции, которые производят бесконечность.
Некоторые операции не имеют математического смысла, например, получение квадратного корня из отрицательного числа. (Да, эта операция имеет смысл в контексте комплексных чисел, но двойное представляет действительное число, и поэтому нет двойного для представления результата.) То же самое верно для логарифмов отрицательных чисел. И sqrt(-1.0), и log(-1.0) будут возвращать NaN, общий термин для "числа", то есть "не числа". Windows отображает NaN как -1.#IND ("IND" для "неопределенного"), в то время как Linux отображает Nan. Другие операции, которые возвращали бы NaN, включают 0/0, 0*∞ и ∞/∞. Смотрите пример кода ниже для примеров.
Короче говоря, если вы получаете 1. # INF или inf, ищите переполнение или деление на ноль. Если вы получаете 1.#IND или nan, ищите нелегальные операции. Может быть, у вас просто есть ошибка. Если он более тонкий, и у вас есть что-то, что сложно вычислить, см. Избежание переполнения, недопущения и потери точности. В этой статье даны приемы для вычисления результатов, которые имеют промежуточные этапы переполнения, если вычисляются напрямую.
Для тех, кто интересуется разницей между -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)
На ваш вопрос "что они" уже ответили выше.
Что касается отладки (ваш второй вопрос) и разработки библиотек, в которых вы хотите проверить наличие специальных входных значений, вы можете найти следующие функции полезными в Windows C++:
_isnan (), _isfinite () и _fpclass()
В Linux/Unix вы должны найти полезными isnan (), isfinite (), isnormal (), isinf (), fpclassify () (и вам может понадобиться связать с libm, используя флаг компилятора -lm).
Для тех из вас, кто работает в среде.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, вы получите следующую ошибку:
Значение было либо слишком большим, либо слишком маленьким для десятичного числа.