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

Получение отрицательного 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 достаточно?

4b9b3361

Ответ 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" в ваших тестовых сценариях.