Получение отрицательного NaN на g ++ 4.4.3, это стандарт? - PullRequest
10 голосов
/ 22 сентября 2010

У меня g ++ 4.4.3 в Linux с Ubuntu Lucid Lynx, и в результате я получаю:

-nan

.На Hardy Heron с g ++ 4.3.1 я получаю все

nan

. Это приводит к сбою регрессии моего текста, поскольку я использую cout для печати этого числового результата.

В чем смысл подписанного nan, и есть ли способ сообщить компилятору, что без знака nan достаточно?

Ответы [ 3 ]

13 голосов
/ 23 сентября 2010

Изменение в поведении может быть связано с библиотеками, а не с компилятором.Конечно, есть изменения в glibc в нужный момент времени - начиная с записи 2009-08-23 в строке 2528 в ChangeLog.17 в источнике glibc:

...
     * stdio-common/printf_fp.c: ISO C expects to print the sign of NaN
     as well.
...
8 голосов
/ 22 сентября 2010

Вы можете получить подписанный 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, указывающий, что это может произойти в будущем.Таким образом, по крайней мере, парень, который следует за вами, поймет, почему.

2 голосов
/ 22 сентября 2010

Возможен подписанный NaN, хотя я не знаю достаточно о плавающей запятой, чтобы знать, почему одна платформа выдаст -NaN, а другая - NaN. Но поскольку NaN ведет себя необычно, я действительно не удивлен, что это может произойти.

Вот фрагмент из описания документа C99 для форматированного ввода-вывода с плавающей запятой:

Двойной аргумент, представляющий NaN конвертируется в один из стилей [-] nan или [-] nan (n-char-последовательность) - какой стиль и смысл любого n-символьная последовательность, есть реализации. F спецификатор преобразования

Вы можете использовать copysign(), чтобы получить знак значения NaN. Пример из документа C99:

if (isnan(c)) c = copysign(0.0, c);

Но , как указывало paxdiablo , может быть проще разрешить результат "-nan" в ваших тестовых скриптах.

...