Як перетворити поплавок у рядок на C ++, одночасно вказавши точність і кількість десяткових цифр?
Наприклад: 3.14159265359 -> "3.14"
Як перетворити поплавок у рядок на C ++, одночасно вказавши точність і кількість десяткових цифр?
Наприклад: 3.14159265359 -> "3.14"
Відповіді:
Типовим способом є використання stringstream
:
#include <iomanip>
#include <sstream>
double pi = 3.14159265359;
std::stringstream stream;
stream << std::fixed << std::setprecision(2) << pi;
std::string s = stream.str();
Дивіться виправлене
Використовуйте фіксовану нотацію з плаваючою комою
Встановлює
floatfield
прапор формату для потоку strfixed
.Коли
floatfield
встановлено значенняfixed
, значення з плаваючою точкою записуються з використанням нотації з фіксованою крапкою: значення представляється рівно стільки цифр у десятковій частині, скільки вказано полем точності (precision
), і без експоненти.
Для перетворень технічного призначення , таких як зберігання даних у файлі XML або JSON, C ++ 17 визначає сімейство функцій to_chars .
Якщо припустити сумісний компілятор (якого нам не вистачає на момент написання статті), можна розглянути щось подібне:
#include <array>
#include <charconv>
double pi = 3.14159265359;
std::array<char, 128> buffer;
auto [ptr, ec] = std::to_chars(buffer.data(), buffer.data() + buffer.size(), pi,
std::chars_format::fixed, 2);
if (ec == std::errc{}) {
std::string s(buffer.data(), ptr);
// ....
}
else {
// error handling
}
Звичайним методом такого роду є "друк у рядок". У C ++ це означає використання std::stringstream
чогось на зразок:
std::stringstream ss;
ss << std::fixed << std::setprecision(2) << number;
std::string mystring = ss.str();
snprintf
в цьому випадку було б краще? Будь ласка , поясніть ... Це , звичайно , не буде швидким, виробляють менше коду [Я написав реалізація Printf, це досить компактний трохи менш як 2000 рядків коду, але з макро - розширень отримує близько 2500 рядків]
__printf_fp
функціональність - досить дивно, що це займає набагато більше часу stringstream
, оскільки цього насправді не повинно бути.
Ви можете використовувати fmt::format
функцію з бібліотеки {fmt} :
#include <fmt/core.h>
int main()
std::string s = fmt::format("{:.2f}", 3.14159265359); // s == "3.14"
}
де 2
точність.
Цей засіб форматування запропоновано для стандартизації на мові C ++: P0645 . І P0645, і {fmt} використовують Python-подібний синтаксис рядкового формату, подібний до синтаксису printf
'', але використовуючи {}
як роздільники замість %
.
Тут рішення використовує лише std. Однак зауважте, що це лише округлюється.
float number = 3.14159;
std::string num_text = std::to_string(number);
std::string rounded = num_text.substr(0, num_text.find(".")+3);
Бо rounded
це дає:
3.14
Код перетворює весь поплавок у рядок, але вирізає всі символи на 2 символи після "."
number + 0.005
у моєму випадку.
Тут я наводжу негативний приклад, коли ви хочете уникати при перетворенні плаваючого числа в рядки.
float num=99.463;
float tmp1=round(num*1000);
float tmp2=tmp1/1000;
cout << tmp1 << " " << tmp2 << " " << to_string(tmp2) << endl;
Ти отримуєш
99463 99.463 99.462997
Примітка: змінною num може бути будь-яке значення, близьке до 99.463, ви отримаєте такий самий роздрук. Суть полягає в тому, щоб уникнути зручної функції c ++ 11 "to_string". Мені знадобився час, щоб вибратися з цієї пастки. Найкращий спосіб - це stringstream і sprintf методи (мова C). С ++ 11 або новіша версія повинна вказувати другий параметр як кількість цифр після плаваючої крапки для показу. Зараз за замовчуванням - 6. Я ставлю це, щоб інші не витрачали час на цю тему.
Я написав свою першу версію. Будь ласка, повідомте мене, якщо знайдете помилку, яку потрібно виправити. Ви можете контролювати точну поведінку за допомогою іоманіпулятора. Моя функція - показувати кількість цифр після десяткової коми.
string ftos(float f, int nd) {
ostringstream ostr;
int tens = stoi("1" + string(nd, '0'));
ostr << round(f*tens)/tens;
return ostr.str();
}