【问题标题】:Convert double to string quickly observing given precision快速将双精度转换为字符串,观察给定的精度
【发布时间】:2016-01-12 13:09:15
【问题描述】:

我有一个使用SDLC++ 程序。在渲染过程中,我需要绘制一些图形组件。我有时需要将double 变量(四舍五入到小数点后一位)转换为std::string

为此,我目前正在使用ostringstream 对象,它工作正常。

std::ostringstream ss;
ss << std::fixed << std::setprecision(1) << x;

但是,我想知道这种转换变量的方式在性能方面是否是个好主意。

我尝试用std::to_string(std::round(x * 10) / 10))double 变量进行四舍五入,但没有成功——我仍然得到类似2.500000000 的输出。

  • 还有其他解决方案吗?
  • ostringstream 是否会产生高额费用?

【问题讨论】:

  • 考虑性能:ostringstream 将使用locale 调用一些开销,否则如果您在渲染调用期间重新使用单个ostringstream(单个分配/内部缓冲区的增长) 那么开销不应超过sprintf
  • 但它不起作用。你应该详细说明。
  • 以防万一您真的意思“它不起作用”,您确实使用 C++11 编译器或您的编译器集进行编译到(至少)C++11 标准,是吗?
  • 我确实使用 C++11 编译器进行了编译。没有改变任何东西。我仍然将变量设置为 2.500000000(例如)。
  • @Q3SanD:嗯,std::setprecision 肯定会转过头来回答这个问题。删除了我的答案,因为它原来是在吠叫错误的树。

标签: c++ sdl ostringstream


【解决方案1】:

您不能使用std::to_string 指定精度,因为它直接等效于带有参数%fprintf(如果使用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;
}

它输出(see on Coliru):

2.50000

2.5

2.500

虽然我没有检查性能...但我认为您甚至可以通过将其封装到一个类中来做得更好(比如只调用一次 std::fixedstd::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 (View on Coliru) 的另一种解决方案:

#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;

}

【讨论】:

  • 它仍在使用ostringstream(我猜没有选择)但它比我的解决方案干净得多。我不会将其标记为答案,但我会支持它。谢谢。
  • @Q3SanD 我添加了另一个没有ostringstream 的解决方案,但我不确定它是否更有效,你应该运行一个板凳。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-11
相关资源
最近更新 更多