Подтвердить что ты не робот

Что делать 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 для чисел с плавающей точкой.

Может ли кто-нибудь перечислить все эти недопустимые значения и что они означают?

4b9b3361

Ответ 1

Из Исключения с плавающей запятой IEEE в С++:

Эта страница ответит на следующие вопросы.

  • Моя программа просто распечатана 1. # IND или 1. # INF (в Windows) или nan или inf (в Linux). Что случилось?
  • Как узнать, действительно ли число действительно число, а не NaN или бесконечность?
  • Как я могу узнать более подробную информацию во время выполнения о типах NaN и бесконечности?
  • Есть ли у вас образец кода, чтобы показать, как это работает?
  • Где я могу узнать больше?

Эти вопросы связаны с исключениями с плавающей запятой. Если вы получаете какой-то странный нечисловый вывод, в котором вы ожидаете число, вы либо превысили конечные пределы арифметики с плавающей запятой, либо попросили получить результат undefined. Чтобы все было просто, я буду работать с двойным типом с плавающей точкой. Аналогичные замечания сохраняются для типов float.

Отладка 1. # IND, 1. # INF, nan и inf

Если ваша операция будет генерировать большее положительное число, чем может быть сохранено в двойном, операция вернет 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, ищите незаконные операции. Может быть, у вас просто ошибка. Если это более тонко, и у вас есть что-то, что сложно вычислить, см. Раздел "Избегать переполнения, недоиспользования и потери точности". В этой статье приводятся трюки для вычисления результатов, которые имеют промежуточное переполнение при вычислении напрямую.

Ответ 2

Для тех из вас, кто находится в среде .NET, следующий способ может быть удобным для фильтрации не-номеров (этот пример находится в VB.NET, но он, вероятно, похож на С#):

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

Если вы попытаетесь использовать переменную с NaN-значением, вы получите следующую ошибку:

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

Ответ 3

Ваш вопрос "что это такое" уже ответил выше.

Что касается отладки (ваш второй вопрос), но и в разработке библиотек, где вы хотите проверить специальные входные значения, в Windows С++ могут быть полезны следующие функции:

_isnan(), _isfinite() и _fpclass()

В Linux/Unix вы должны найти isnan(), isfinite(), isnormal(), isinf(), fpclassify() полезным (и вам может потребоваться ссылка на libm с помощью флага -lm компилятора).