在 C++ 中将浮点数转换为 std::string
Posted
技术标签:
【中文标题】在 C++ 中将浮点数转换为 std::string【英文标题】:Convert float to std::string in C++ 【发布时间】:2011-01-08 17:06:36 【问题描述】:我有一个浮点值需要放入std::string
。如何从浮点数转换为字符串?
float val = 2.5;
std::string my_val = val; // error here
【问题讨论】:
考虑阅读 Herb Sutter 的文章“庄园农场的字符串格式化程序”(gotw.ca/publications/mill19.htm)。它提供了五种最常见的格式化方式的示例,并讨论了它们的优缺点。 【参考方案1】:从 C++11 开始,标准 C++ 库为函数 std::to_string(arg)
提供了各种支持的 arg
类型。
【讨论】:
在使用浮点数时注意 std::to_string() 可能出现的意外行为。 (请参阅此链接en.cppreference.com/w/cpp/string/basic_string/to_string 上的示例输出)。 这应该被提升为最佳答案,因为大多数构建环境已经支持 C++11【参考方案2】:除非您担心性能,否则请使用string streams:
#include <sstream>
//..
std::ostringstream ss;
ss << myFloat;
std::string s(ss.str());
如果您对 Boost 没问题,lexical_cast<> 是一个方便的选择:
std::string s = boost::lexical_cast<std::string>(myFloat);
有效的替代品是例如FastFormat 或简单的 C 风格函数。
【讨论】:
考虑到这些函数很少被调用(调整窗口大小),这将是一个足够的解决方案,但是有没有更有效的方法? 如果您对 Boost 不满意,请编写您自己的词法转换函数;大约只有五行代码,构成了一个最有用的库函数(请参阅gotw.ca/publications/mill19.htm 了解基本实现)。 第一种方法,别忘了#include <sstream>
。
@jackw11111,标题是一个非常重要的点,在答案中经常被忽略。 c++ 'streams' 尤其成问题。感谢您指出。如果你没有,我会这样做。【参考方案3】:
重要: 阅读最后的说明。
快速回答:
使用to_string()
。 (从 c++11 开始可用)
示例:
#include <iostream>
#include <string>
using namespace std;
int main ()
string pi = "pi is " + to_string(3.1415926);
cout<< "pi = "<< pi << endl;
return 0;
自己运行:http://ideone.com/7ejfaU 这些也可用:
string to_string (int val);
string to_string (long val);
string to_string (long long val);
string to_string (unsigned val);
string to_string (unsigned long val);
string to_string (unsigned long long val);
string to_string (float val);
string to_string (double val);
string to_string (long double val);
重要提示:
正如@Michael Konečný 正确指出的那样,使用to_string()
充其量是有风险的,这很可能会导致意想不到的结果。
来自http://en.cppreference.com/w/cpp/string/basic_string/to_string:
使用浮点类型
std::to_string
可能产生意外结果,因为返回的字符串中的有效位数可以为零,请参见示例。 返回值可能与std::cout
默认打印的值有很大不同,请参见示例。std::to_string
依赖于当前语言环境进行格式化,因此并发调用std::to_string
从 多个线程可能会导致调用的部分序列化。C++17
提供std::to_chars
作为更高性能的独立于语言环境的 替代。
最好的方法是使用stringstream
,就像@dcp 在his answer 中展示的那样。:
以下示例演示了此问题: 自己运行示例:https://www.jdoodle.com/embed/v0/T4k
#include <iostream>
#include <sstream>
#include <string>
template < typename Type > std::string to_str (const Type & t)
std::ostringstream os;
os << t;
return os.str ();
int main ()
// more info : https://en.cppreference.com/w/cpp/string/basic_string/to_string
double f = 23.43;
double f2 = 1e-9;
double f3 = 1e40;
double f4 = 1e-40;
double f5 = 123456789;
std::string f_str = std::to_string (f);
std::string f_str2 = std::to_string (f2); // Note: returns "0.000000"
std::string f_str3 = std::to_string (f3); // Note: Does not return "1e+40".
std::string f_str4 = std::to_string (f4); // Note: returns "0.000000"
std::string f_str5 = std::to_string (f5);
std::cout << "std::cout: " << f << '\n'
<< "to_string: " << f_str << '\n'
<< "ostringstream: " << to_str (f) << "\n\n"
<< "std::cout: " << f2 << '\n'
<< "to_string: " << f_str2 << '\n'
<< "ostringstream: " << to_str (f2) << "\n\n"
<< "std::cout: " << f3 << '\n'
<< "to_string: " << f_str3 << '\n'
<< "ostringstream: " << to_str (f3) << "\n\n"
<< "std::cout: " << f4 << '\n'
<< "to_string: " << f_str4 << '\n'
<< "ostringstream: " << to_str (f4) << "\n\n"
<< "std::cout: " << f5 << '\n'
<< "to_string: " << f_str5 << '\n'
<< "ostringstream: " << to_str (f5) << '\n';
return 0;
输出:
std::cout: 23.43
to_string: 23.430000
ostringstream: 23.43
std::cout: 1e-09
to_string: 0.000000
ostringstream: 1e-09
std::cout: 1e+40
to_string: 10000000000000000303786028427003666890752.000000
ostringstream: 1e+40
std::cout: 1e-40
to_string: 0.000000
ostringstream: 1e-40
std::cout: 1.23457e+08
to_string: 123456789.000000
ostringstream: 1.23457e+08
【讨论】:
在使用浮点数时注意 std::to_string() 可能出现的意外行为。 (请参阅此链接en.cppreference.com/w/cpp/string/basic_string/to_string 上的示例输出)。【参考方案4】:您可以定义一个模板,该模板不仅适用于双打,也适用于其他类型。
template <typename T> string tostr(const T& t)
ostringstream os;
os<<t;
return os.str();
然后你可以将它用于其他类型。
double x = 14.4;
int y = 21;
string sx = tostr(x);
string sy = tostr(y);
【讨论】:
【参考方案5】:在您的标准库提供std::to_chars
后使用它:
std::array<char, 32> buf;
auto result = std::to_chars(buf.data(), buf.data() + buf.size(), val);
if (result.ec == std::errc())
auto str = std::string(buf.data(), result.ptr - buf.data());
// use the string
else
// handle the error
这种方法的优点是:
它独立于语言环境,可防止在将数据写入需要“.”的 JSON 等格式时出现错误。作为小数点 它提供最短的十进制表示和往返保证 它可能比其他标准方法更有效,因为它不使用语言环境并且不需要分配不幸的是,std::to_string
对浮点的实用性有限,因为它使用固定表示,将小值四舍五入为零并为大值生成长字符串,例如
auto s1 = std::to_string(1e+40);
// s1 == 10000000000000000303786028427003666890752.000000
auto s2 = std::to_string(1e-40);
// s2 == 0.000000
如果P0645 标准提案获得批准,C++20 可能会获得更方便的std::format
API,其优势与std::to_chars
相同。
【讨论】:
【参考方案6】:你可以在 C++11 中使用std::to_string
float val = 2.5;
std::string my_val = std::to_string(val);
【讨论】:
注意,不要复制-粘贴-提交-grace_period_edit 答案。复制粘贴编辑提交它们。我们得到一个自动标志。下次小心点。干杯 这与@dmckee 2013 年的回答基本相同。 @Yochai 当我cout
my_val
给出 5.20000 但当您将 val
分配给 50.2 或更大时,它给出的输出不准确。给出如下:50.000001 和 107.199997(对于 107.2)。这是什么原因?【参考方案7】:
如果您担心性能,请查看Boost::lexical_cast 库。
【讨论】:
我认为您的意思是“如果您不担心性能”。boost::lexical_cast
是您可以选择的最重的解决方案!【参考方案8】:
This tutorial 给出了一个简单而优雅的解决方案,我将其转录:
#include <sstream>
#include <string>
#include <stdexcept>
class BadConversion : public std::runtime_error
public:
BadConversion(std::string const& s)
: std::runtime_error(s)
;
inline std::string stringify(double x)
std::ostringstream o;
if (!(o << x))
throw BadConversion("stringify(double)");
return o.str();
...
std::string my_val = stringify(val);
【讨论】:
以上是关于在 C++ 中将浮点数转换为 std::string的主要内容,如果未能解决你的问题,请参考以下文章