Какое значение float делает sprintf_s() "1. QO"?
У меня есть некоторый (устаревший вложенный c) код, который создает CSV файл с помощью некоторых вызовов sprintf
. Иногда я вижу значения 1.#QO
. Я попытался воспроизвести эти значения с условиями, которые должны дать отрицательную бесконечность, положительную бесконечность и NaN, но ни один из них не дает мне магического результата 1.#QO
. Итак, что же это такое?
... и да, я знаю, что, очевидно, что-то не так в математике, которая производит эту ценность, но понимание того, что это означает, поможет в отладке.
[Изменить 1] Фактическая строка, которая выполняет преобразование:
sprintf_s(txt, CSV_HEADER_SIZE, "%.3f", value);
где:
#define CSV_HEADER_SIZE (100)
char txt[CSV_HEADER_SIZE];
Я компилирую с MS Visual Studio 2008.
[Edit 2] Немного больше показов 0xFFFFFFFF
дает -1.#QO
:
unsigned int i = 0xFFFFFFFF;
float* f = (float*)&i;
printf("%.3f", *f); // gives -1.#QO
.. и глядя на то, что в отладчике Visual Studio расширяет его до -1.#QNAN00
, поэтому похоже, что это, вероятно, Microsoft-специфическое представление NaN
?
Ответы
Ответ 1
"- 1. # QO" - "-1. # QNAN" после "округления" для 3-х мест после десятичного. N округляет до O как "A" >= "5" и "N" + 1 == "O".
Аналогичным образом, ваш отладчик показывает "-1. # QNAN00", поскольку он печатает с 7 местами и добавляет нулевые корни до конца.
QNaN тихий NaN.
Ответ 2
После многократного разговора я могу окончательно сказать, что установка 4-байтового float на 0x7FFFFFFF
и передача его в sprintf_s
с помощью спецификатора формата %.3f
- это то, что дало мне 1.#QO
:
const int bufSize = 100;
char buf[bufSize];
unsigned int i;
float* f = (float*)&i;
int retval;
i = 0xFFFFFFFF;
retval = sprintf_s(buf, bufSize, "%.3f\n", *f);
printf("sprintf_s returned %d, converted val = %s", retval, buf); // == sprintf_s returned 7, converted val = -1.#QO
retval = sprintf_s(buf, bufSize, "%f\n", *f);
printf("sprintf_s returned %d, converted val = %s", retval, buf); // == sprintf_s returned 10, converted val = -1.#QNAN0
i = 0x7FFFFFFF;
retval = sprintf_s(buf, bufSize, "%.3f\n", *f);
printf("sprintf_s returned %d, converted val = %s", retval, buf); // == sprintf_s returned 6, converted val = 1.#QO
retval = sprintf_s(buf, bufSize, "%f\n", *f);
printf("sprintf_s returned %d, converted val = %s", retval, buf); // == sprintf_s returned 9, converted val = 1.#QNAN0
... кажется, что спецификатор формата %.3f
обрезал результат NAN, так что должно было быть 1.#QNAN0
разбито на 1.#QO
.
Ответ 3
Маленький поисковый запрос указывает на ошибку деления на 0. Хотя я бы ожидал чего-то другого, если бы это было так. Тем не менее, он, по-видимому, специфичен для MS/Visual C.
Ответ 4
Вы проверили, вызвал ли sprintf_s() отказ? Если это так, вы не должны использовать результат. Поскольку код не выглядит так, как вы отметили, я думаю, вы должны сделать эту проверку. Фактически, если вы не тестируете результат из одной из функций *_s()
, вы направляетесь на неприятности.