Конвертируйте 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;

}
Другие вопросы по тегам