gcvt()
дает противоречивые значения в Linux и Windows и считается устаревшим.
Пример:
char no[100];
double x = 0.00949999999998;
gcvt(x, 16, no);
printf("%s", no);
В винде выдает - 9.4999999998e-003
В Linux это дает — 0,0094999999998.
В Linux он выдает выходную строку в экспоненциальном формате, когда значение очень мало.
Я не могу найти функцию, которая дает последовательный вывод (очень имитируя gcvt()
в Linux) независимо от платформы.
Я пробовал использовать snprintf()
и некоторые другие функции, но, хотя они дают одинаковый результат в Windows и Linux, они не имитируют gcvt()
. Я хотел, чтобы новая функция точно имитировала поведение Linux.
В упомянутом примере snprintf() дает 0,009500. И не хватает точности. Я знаю, что мы можем установить точность, но динамически она не регулирует ее, как это делает gcvt().
Когда POSIX удалил это, в качестве замены рекомендовался sprintf()
. Я думаю, они ожидают, что вы сделаете правильный выбор между %E
и %F
и укажете желаемую точность.
Точного эквивалента нет, это лучшее, что вы можете сделать.
Это облом :\
Какой формат вы использовали с sprintf()
? Если вы используете формат %.16g
, вы, вероятно, приблизитесь к тому, что ожидаете. Посмотрите спецификацию %g
(например, спецификацию POSIX sprintf() или стандарт C11 для fprintf()), чтобы узнать, как можно настроить представление в соответствии с вашими требованиями. Однако я боюсь, что вас может обмануть то, что Windows ведет себя иначе, чем Linux, в вашем примере.
Рассматривали ли вы возможность заимствовать код Linux для gcvt()
, переименовать функцию (во избежание конфликтов) и использовать ее вместо версии, предоставленной системой? Если вы везде используете один и тот же код, вы должны везде получить один и тот же результат.
Попробую, но поскольку, наконец, это системный API Win32 и API Linux, я не совсем уверен, что конечный результат будет другим.
Спецификация формата %g
— это обобщенный формат чисел с плавающей запятой; он преобразует очень большие и очень маленькие числа в экспоненциальную запись (например, %e
) и сохраняет умеренные числа в записи с фиксированной запятой (например, %f
).
На MacBook Pro этот код:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char no[100];
double x = 0.00949999999998;
gcvt(x, 16, no);
printf("%s\n", no);
printf("%.16g\n", x);
return 0;
}
дает результат:
9.49999999998e-03
0.00949999999998
Кажется, это соответствует вашему предпочтительному результату. У меня нет компьютера с Windows, на котором я мог бы протестировать, поэтому я не могу ответить, как там ведет себя код.
Обратите внимание, что ecvt(), fcvt() и gcvt() были помечены как устаревшие в POSIX 2004 и удалены из POSIX 2008.
Есть небольшая разница с MSVC: первый выводится как 9.49999999998e-003
.
Ключевой вопрос заключается в том, есть ли разница в выводе %.16g
. Если нет, то проблема ОП решена. Если разница все еще существует, например, 2 или 3 цифры в экспоненте при печати экспоненты, то идентичный вывод будет невозможен без использования общего кода (что означает «не использовать предоставляемое системой семейство функций printf()
или функция gcvt()
").
Проблема с "%.16g" заключается в том, что если x = 1,0, snprintf() по-прежнему печатает 1.000... вместо 1, как печатает gcvt().
На MacOS модифицированная версия тестовой программы выдаёт: gcvt: [9.49999999998e-03], printf: [0.00949999999998]
— gcvt: [1], printf: [1]
. Второй результат — обработка double y = 1.0;
.
Какая функциональность
gcvt()
отсутствует вsprintf()
?