代码之家  ›  专栏  ›  技术社区  ›  David Dolson

C++:将双转换为字符串的最佳方法是什么?

c c++
  •  12
  • David Dolson  · 技术社区  · 17 年前

    最重要的是什么 最优的 如何做到这一点?

    void foo(double floatValue, char* stringResult)
    {
        sprintf(stringResult, "%f", floatValue);
    }
    
    12 回复  |  直到 7 年前
        1
  •  2
  •   David    17 年前

    我可能会同意您在问题中的建议,因为没有内置的ftoa()函数,sprintf提供了对格式的控制。谷歌搜索“ftoa asm”会得到一些可能有用的结果,但我不确定你是否想这么做。

        2
  •  23
  •   Tyler McHenry    17 年前

    我相信有人会说boost::lexical-cast,所以如果你在使用boost,那就说吧,但无论如何,它基本上是相同的:

     #include <sstream>
     #include <string>
    
     std::string doubleToString(double d)
     {
        std::ostringstream ss;
        ss << d;
        return ss.str();
     }
    

    请注意,您可以很容易地将其转换为一个模板,该模板可以处理任何可以插入流的内容(而不仅仅是双模板)。

        3
  •  10
  •   phuclv    8 年前

    http://www.cplusplus.com/reference/iostream/stringstream/

    double d=123.456;
    stringstream s;
    s << d; // insert d into s
    
        4
  •  4
  •   greyfade    17 年前

    促进:: lexical_cast &;

        5
  •  4
  •   pgast    17 年前

    在Dinkumware STL上,字符串流由C库snprintf填充。

    因此,直接使用snprintf格式将与stl格式部分相当。 但有人曾经告诉我,整体大于或等于其已知部分之和。

    因为它将依赖于平台,以确定Stringstream是否会进行分配(我非常肯定,Dinkumware还没有在Stringstream中包含一个小的缓冲区,用于转换像您这样的单个项目),所以确实怀疑任何需要分配(尤其是多线程)的东西都能与snprintf竞争。

    事实上(格式化+分配)有可能非常糟糕,因为一个分配和一个发行版可能需要在多线程环境中进行2个完整的读-修改-写循环,除非分配实现有一个线程本地小堆。

    也就是说,如果我真的关心性能,我会接受上面其他一些评论的建议,更改接口以包含一个大小并使用snprintf-即。

    bool 
    foo(const double d, char* const p, const size_t n){
         use snprintf......
         determine if it fit, etc etc etc.
    }
    

    如果您想要一个std::string,那么最好使用上面的方法并从结果char*中实例化字符串,因为std::stringstream、std::string解决方案将涉及2个分配+2个发布。

    顺便说一句,我不知道问题中的“字符串”是std::string还是只是“string”的通用ASCII字符用法。

        6
  •  3
  •   hb2pencil    17 年前

    最好的做法是构建一个简单的模板化函数,将任何可流类型转换为字符串。我是这样做的:

    #include <sstream>
    #include <string>
    
    template <typename T>
    const std::string to_string(const T& data)
    {
       std::ostringstream conv;
       conv << data;
       return conv.str();
    }
    

    如果您想要一个const char*表示,只需替换上面的conv.str().c_str()。

        7
  •  2
  •   Michael Krelin - hacker    17 年前

    我会说 sprintf 是最理想的方法。你可能更喜欢 snprintf 但这与性能没有太大关系。

        8
  •  1
  •   OneOfOne    17 年前

    如果您使用qt4框架,您可以:

    double d = 5.5;
    QString num = QString::number(d);
    
        9
  •  1
  •   user1115652    15 年前

    Herb Sutter对将int转换为字符串的替代方法做了广泛的研究,但我认为他的论点也适用于double。

    他研究了模板中安全性、效率、代码清晰性和可用性之间的平衡。

    在这里阅读: http://www.gotw.ca/publications/mill19.htm

        10
  •  0
  •   MSN    17 年前

    _gcvt 或 _gcvt_s .

        11
  •  0
  •   Patel    11 年前

    这是一条非常有用的线。我使用sprintf_,但我开始怀疑它是否真的比其他方法更快。我在Boost网站上看到了以下文档,其中显示了printf/scanf、stringstream和boost之间的性能比较。

    double-to-string是我们在代码中进行的最常见的转换,所以我将坚持使用我一直使用的方法。但是,在其他场景中使用boost可能是您的决定因素。

    http://www.boost.org/doc/libs/1_58_0/doc/html/boost_lexical_cast/performance.html

        12
  •  0
  •   Porsche9II    7 年前

    将来,你可以使用 std::to_chars 像这样写代码 https://godbolt.org/z/cEO4Sd . 不幸的是,只有VS2017和VS2019支持此功能的一部分…

    #include <iostream>
    #include <charconv>
    #include <system_error>
    #include <string_view>
    #include <array>
    
    int main()
    {
        std::array<char, 10> chars;
        auto [parsed, error] = std::to_chars(
            chars.data(), 
            chars.data() + chars.size(), 
            static_cast<double>(12345.234)
        );
        std::cout << std::string_view(chars.data(), parsed - chars.data());
    }
    

    有关MSVC详细信息的详细讨论,请参阅 https://www.reddit.com/r/cpp/comments/a2mpaj/how_to_use_the_newest_c_string_conversion/eazo82q/