Конвертируйте double в string, быстро соблюдая заданную точность
У меня есть C++
программа с использованием SDL
, Во время рендеринга мне нужно нарисовать некоторые графические компоненты. Мне иногда нужно конвертировать double
переменные, округленные до одного десятичного знака, до std::string
,
Для этого я сейчас использую ostringstream
объект и работает нормально.
std::ostringstream ss;
ss << std::fixed << std::setprecision(1) << x;
Тем не менее, мне интересно, если этот способ преобразования переменных является хорошей идеей в отношении производительности.
Я пытался округлить double
переменные с std::to_string(std::round(x * 10) / 10))
, но это не сработало - я все равно получил вывод как 2.500000000
,
- Есть ли другое решение?
- Есть ли
ostringstream
понести большие расходы?
1 ответ
Вы не можете указать точность с std::to_string
так как это прямой эквивалент printf
с параметром %f
(при использовании double
).
Если вы беспокоитесь о том, чтобы не выделять каждый раз поток, вы можете сделать следующее:
#include <iostream>
#include <sstream>
#include <iomanip>
std::string convertToString(const double & x, const int & precision = 1)
{
static std::ostringstream ss;
ss.str(""); // don't forget to empty the stream
ss << std::fixed << std::setprecision(precision) << x;
return ss.str();
}
int main() {
double x = 2.50000;
std::cout << convertToString(x, 5) << std::endl;
std::cout << convertToString(x, 1) << std::endl;
std::cout << convertToString(x, 3) << std::endl;
return 0;
}
Это выводит ( см. На Coliru):
2,50000
2.5
2,500
Я не проверял производительность, хотя... но я думаю, что вы могли бы добиться большего успеха, заключив это в класс (как, например, вызов std::fixed
а также std::precision
один раз).
В противном случае, вы все еще можете использовать sprintf
с параметрами, которые вам подходят.
Пройдем немного дальше, с инкапсулирующим классом, который вы можете использовать в качестве статического экземпляра или члена другого класса... по вашему желанию ( View on Coliru).
#include <iostream>
#include <sstream>
#include <iomanip>
class DoubleToString
{
public:
DoubleToString(const unsigned int & precision = 1)
{
_ss << std::fixed;
_ss << std::setprecision(precision);
}
std::string operator() (const double & x)
{
_ss.str("");
_ss << x;
return _ss.str();
}
private:
std::ostringstream _ss;
};
int main() {
double x = 2.50000;
DoubleToString converter;
std::cout << converter(x) << std::endl;
return 0;
}
Другое решение без использования ostringstream
( Посмотреть на Колиру):
#include <iostream>
#include <string>
#include <memory>
std::string my_to_string(const double & value) {
const int length = std::snprintf(nullptr, 0, "%.1f", value);
std::unique_ptr<char[]> buf(new char[length + 1]);
std::snprintf(buf.get(), length + 1, "%.1f", value);
return std::string(buf.get());
}
int main(int argc, char * argv[])
{
std::cout << my_to_string(argc) << std::endl;
std::cout << my_to_string(2.5156) << std::endl;
}