Что означают 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, вы получите следующую ошибку:

Значение было либо слишком большим, либо слишком маленьким для десятичного числа.

Другие вопросы по тегам