Как конвертировать float/double в строку именно в том виде, в котором значение устновленно в переменной (без обрезки занков)?

К своему удивлению не нашёл функции записи float/double в строку в исходном виде переменной:

float val = 0.012345678900000;
std::string strval;
snprintf(&strval[0], strval.capacity(), "%g", val);
printf("%s\n", strval.data());

Выводит "0.01234567", а надо "0.012345678900000". stringstream пробовал - результат тот же. std::to_string вообще 6 знаков пишет после точки. Точность заранее не известна, нужно выгружать в строку то, что есть, можно без нулей в конце.

Как это сделать?


Ответы (1 шт):

Автор решения: Harry
float  valf = 0.012345678900100;
double vald = 0.012345678900100;
printf("%.20f\n", valf);
printf("%.20lf\n", vald);

Вывод:

0.01234567910432815552
0.01234567890010000030

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

Пробуйте

char buf[30];
sprintf(buf,"%.20lf",val);
string s = buf;

Или

ostringstream os;
os << setprecision(20) << vald;
string s = os.str();
cout << s << endl;

Только не пишите в никуда, как в вашем примере...

Update

К "артефактам", упомянутым в комментарии. Это не артефакты. Представим, что у нас есть возможность записи только 4 бит. Как вы представите, например, 1/5 в виде суммы дробей вида 1/2n?

1/8 + 1/16 + 1/128... Стоп! Уже не можем представить 1/128 - точности не хватает. Так что число 0.20 будет иметь вид 0.1875.

Это - ограничение самого представления. Ну невозможно в общем случае представить дробное число с помощью конечной суммы дробей вида 1/2n...

→ Ссылка