Получение отрицательного NaN на g++ 4.4.3, является ли этот стандарт?
У меня есть g++ 4.4.3 на Linux с Ubuntu Lucid Lynx, и я получаю:
-nan
. На Hardy Heron с g++ 4.3.1 я получаю все
нан
Это приводит к тому, что моя регрессия diff diff не работает, поскольку я использую cout для печати этого численного результата.
В чем смысл подписанного nan, и есть ли способ сказать компилятору, что unsigned nan достаточно?
Ответы
Ответ 1
Изменение поведения может быть связано с библиотеками, а не с компилятором. Конечно, есть изменения в glibc вокруг правильного времени - из записи для 2009-08-23 в строке 2528 в ChangeLog.17
в источнике glibc:
...
* stdio-common/printf_fp.c: ISO C expects to print the sign of NaN
as well.
...
Ответ 2
Вы можете получить подписанный NaN, так как NaN-значение значения и знак значения управляются разными битами в IEEE754 (NaN просто указывается специальными значениями экспоненты, отличными от знакового бита). Я не понимаю, что это за операция.
Возможно, что одна из нормальных операций, которые производят NaN, может вызвать отрицательную вариацию (например, +0/-0
или +Inf/-Inf
). Но я бы подумал, что NaN будут печататься как nan
независимо от знака.
Однако, хотя стандарт подробно описывает, как обрабатываются числа, он странно молчит о том, как они печатаются. страница Википедии для NaN перечисляет эти данные:
nan NaN NaN% NAN NaNQ
NaNS qNaN sNaN 1.#SNAN 1.#QNAN
-1.#IND -NaN NaN12345 -sNaN12300
с некоторыми из тех, которые показывают знак и дополнительную полезную нагрузку.
Обратите внимание, что я говорю о стандартах IEEE. Стандарты ISO C указывают на ограниченное количество форм, но независимо от того, печатается ли знак и/или полезная нагрузка, зависит от реализации. Я могу только предположить, что более поздние версии библиотеки изменили свое поведение.
Как исправить это в компиляторе, я не уверен. Я бы просто принял прагматичный подход и запустил выходной файл с помощью sed 's/-nan/nan/g'
. Надеюсь, это не вызовет других проблем.
И вы также должны следить за формой, которая позволяет печатать полезную нагрузку, хотя я бы только беспокоился об этом, когда тесты снова начнут сбой. Но я бы добавил комментарий рядом с этой командой sed
, указывающей, что это может произойти в будущем. Таким образом, по крайней мере, тот, кто следует за вами, поймет, почему.
Ответ 3
Подписанный NaN возможен, хотя я не знаю достаточно о плавающей точке, чтобы знать, почему одна платформа будет производить -NaN, а другая будет производить NaN. Но так как NaN имеет некоторые необычные поведения, я действительно не удивлен, что это может произойти.
Здесь приведен фрагмент из описания документа C99 для форматированного ввода/вывода с плавающей запятой:
Двойной аргумент, представляющий собой NaN преобразуется в один из стилей [-] nan или [-] nan (n- char -последовательность) - какой стиль и какой смысл n- char -последовательность, реализации. F спецификатор преобразования
Вы можете использовать copysign()
для получения знака значения NaN. Пример из документа C99:
if (isnan(c)) c = copysign(0.0, c);
Но как указано paxdiablo, может быть проще разрешить результат "-nan" в ваших тестовых сценариях.