std::string 浮动或加倍
Posted
技术标签:
【中文标题】std::string 浮动或加倍【英文标题】:std::string to float or double 【发布时间】:2009-06-18 13:15:58 【问题描述】:我正在尝试将std::string
转换为float/double
。
我试过了:
std::string num = "0.6";
double temp = (double)atof(num.c_str());
但它总是返回零。还有其他方法吗?
【问题讨论】:
克制过度设计十年前就已经发现的东西的冲动。 您确定输出正确吗?它不应该产生零 另外,你不需要转换 atof,它已经返回一个 double。 我确定。调试器显示 0。结果为 0。平台:Linux。 您确定安装了正确的语言环境吗?试试 "0,6" 或 setlocale(LC_NUMERIC, "C"); 【参考方案1】:std::string num = "0.6";
double temp = ::atof(num.c_str());
对我有用吗,将字符串转换为双精度值是有效的 C++ 语法。
您可以使用 stringstream 或 boost::lexical_cast 来做到这一点,但它们会带来性能损失。
啊哈哈,你有一个 Qt 项目...
QString winOpacity("0.6");
double temp = winOpacity.toDouble();
补充说明:
如果输入数据是const char*
,QByteArray::toDouble
会更快。
【讨论】:
boost::lexical_cast 正在流式传输。 我认为,您通常不能说它们会带来性能损失。想想当你有一个 cin >> num; 之前会发生什么。用户必须非常快速地输入(像 rly jon skeet 一样)才能注意到 lexical_cast 的毫秒数更慢 :) 就是说,我相信有些任务 lexical_cast 会降低性能 :) 对于这个解决方案,atof() 前面的 :: 是做什么的?它需要在那里? @ShaChris 因为我想确保使用全局命名空间中的 atof 函数。 取决于当前语言环境【参考方案2】:标准库 (C++11) 通过 std::stod
提供所需的功能:
std::string s = "0.6"
std::wstring ws = "0.7"
double d = std::stod(s);
double dw = std::stod(ws);
通常对于大多数其他基本类型,请参阅<string>
。 C 字符串也有一些新功能。见<stdlib.h>
【讨论】:
我喜欢这个解决方案,但它似乎只来自 C++11。所以在我的 SDK 上不可用。 很高兴知道 C++ 标准委员会添加了这个。ostringstream
本身太长了,无法输入,更不用说使用 ..
对于浮点数(正如我在谷歌通过键入“c++ string to float”发现的问题中所问的那样),应该使用 std::stof。
请注意,这可能会引发异常:std::invalid_argument(如果转换失败)std::out_of_range(如果超出范围)
买家注意,取决于当前的语言环境。【参考方案3】:
词法转换非常好。
#include <boost/lexical_cast.hpp>
#include <iostream>
#include <string>
using std::endl;
using std::cout;
using std::string;
using boost::lexical_cast;
int main()
string str = "0.6";
double dub = lexical_cast<double>(str);
cout << dub << endl;
【讨论】:
谢谢,它可以工作。但对我来说这是一个问题:为什么我的代码不工作。 @Johannes Schaub:基于ADL,他还不如拥有,使用定义加上他实际使用的定义可能会将大量std元素带入范围。此外 lexical_cast 非常慢,所以我没有 +1。 boost::lexical_cast 的一个很好的特性是错误处理。如果转换失败,则抛出异常:try ... boost::lexical_cast ... catch (std::exception const& err) //handle excpetion
更准确地说,使用catch ( boost::bad_lexical_cast const& err )
捕获异常。【参考方案4】:
你可以使用 std::stringstream:
#include <sstream>
#include <string>
template<typename T>
T StringToNumber(const std::string& numberAsString)
T valor;
std::stringstream stream(numberAsString);
stream >> valor;
if (stream.fail())
std::runtime_error e(numberAsString);
throw e;
return valor;
用法:
double number= StringToNumber<double>("0.6");
【讨论】:
嗯,所以你认为 boost::lexical_cast 的接口很糟糕,不是吗?看看 stefanB 的回答! Boost 也是如此。 @kirsche40 对于尚未依赖 Boost 的人来说,这似乎是一个不错的选择(与 Boost 链接只是为了将 std::string 转换为数字有点矫枉过正!) @JEan-Phillippe Jodiun 我回复了一条现已删除的评论,其中有人推荐了 Boost。我知道 Boost 在大多数情况下都是矫枉过正的。顺便说一句,一段时间以来,Boost 的使用仅限于“较新”的编译器。旧项目不能使用 Boost。例如,ASIO 严重依赖于 std::addressof 等 C++11 特性,这使得它对于 C++98/C++03 编译器完全没有价值。恕我直言,当项目开始时,Boost 的目的是为旧编译器版本提供新的“标准化”功能...... :-(【参考方案5】:是的,有一个词法转换。使用 stringstream 和
您自己的版本可能如下所示:
template<typename to, typename from>to lexical_cast(from const &x)
std::stringstream os;
to ret;
os << x;
os >> ret;
return ret;
【讨论】:
【参考方案6】:你可以使用 boost 词法转换:
#include <boost/lexical_cast.hpp>
string v("0.6");
double dd = boost::lexical_cast<double>(v);
cout << dd << endl;
注意:boost::lexical_cast 会抛出异常,所以当你传递无效值时你应该准备好处理它,尝试传递 string("xxx")
【讨论】:
【参考方案7】:如果您不想拖入所有的 boost,请使用 strtod(3)
from <cstdlib>
- 它已经返回一个 double。
#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
using namespace std;
int main()
std::string num = "0.6";
double temp = ::strtod(num.c_str(), 0);
cout << num << " " << temp << endl;
return 0;
输出:
$ g++ -o s s.cc
$ ./s
0.6 0.6
$
为什么 atof() 不起作用...你在什么平台/编译器上?
【讨论】:
使用字符串流不需要提升 您的方法也返回零。 Linux。【参考方案8】:我在 Linux 中遇到了同样的问题
double s2f(string str)
istringstream buffer(str);
double temp;
buffer >> temp;
return temp;
它有效。
【讨论】:
【参考方案9】: double myAtof ( string &num)
double tmp;
sscanf ( num.c_str(), "%lf" , &tmp);
return tmp;
【讨论】:
无效答案,你怎么知道num中存储的值实际上是一个有效的浮点数?你不检查 sscanf 的返回类型,似乎是一种 MS 编码风格。【参考方案10】:C++ 11 的方式是使用 std::stod 和 std::to_string。两者都适用于 Visual Studio 11。
【讨论】:
【参考方案11】:在 C++17 中,您可以使用std::from_chars
,它是std::stof
和std::stod
的更轻、更快的替代品。它不涉及任何内存分配或查看语言环境,并且不会抛出。
std::from_chars
函数返回一个from_chars_result
类型的值,它基本上是一个具有两个字段的结构:
struct from_chars_result
const char* ptr;
std::errc ec;
;
通过检查ec
,我们可以判断转换是否成功:
#include <iostream>
#include <charconv>
int main()
const std::string str "12345678901234.123456" ;
double value = 0.0;
auto [p, ec] = std::from_chars(str.data(), str.data() + str.size(), value);
if (ec != std::errc())
std::cout << "Couldn't convert value";
return 0;
注意:您需要一个相当最新的编译器(例如 gcc11),以便 std::from_chars
处理浮点类型。
【讨论】:
【参考方案12】:这个答案是在你的 cmets 中备份 litb。我非常怀疑您只是没有正确显示结果。
我曾经发生过完全相同的事情。我花了一整天的时间试图弄清楚为什么我在 64 位 int 中得到了一个错误的值,结果却发现 printf 忽略了第二个字节。您不能像 int 一样将 64 位值传递给 printf。
【讨论】:
我没有使用 printf 查看结果...并且我使用该值来设置窗口不透明度,并且我的窗口是完全透明的,因此值为 0。【参考方案13】:至于为什么atof()
在最初的问题中不起作用:它被转换为 double 的事实让我感到怀疑。如果没有#include <stdlib.h>
,代码不应编译,但如果添加强制转换以解决编译警告,则atof()
未正确声明。如果编译器假定 atof()
返回一个 int,则强制转换它会解决转换警告,但它不会导致返回值被识别为双精度值。
#include <stdlib.h>
#include <string>
...
std::string num = "0.6";
double temp = atof(num.c_str());
应该在没有警告的情况下工作。
【讨论】:
【参考方案14】:您可以(暂时)将字符串保留为char[]
并使用sprintf()
,而不是将Boost 拖入方程式。
当然,如果您仍然使用 Boost,这真的不是什么大问题。
【讨论】:
【参考方案15】:无论如何,您都不希望 Boost lexical_cast 用于字符串 浮点。该用例子集是唯一一个 boost 始终比旧功能更差的集合——它们基本上将所有故障都集中在那里,因为它们自己的性能结果显示,与使用 sscanf 和 printf 进行此类转换相比,它们的性能要慢 20-25 倍。
自己谷歌一下。 boost::lexical_cast 可以处理类似 50 次转换,如果您排除涉及浮点 #s 的转换,它与明显的替代方案一样好或更好(具有所有这些操作的单一 API 的额外优势)。但是带上花车,就性能而言,它就像泰坦尼克号撞上冰山一样。
旧的专用 str->double 函数都可以在 30 毫秒(或更好)内完成 10000 次解析。 lexical_cast 需要大约 650 毫秒来完成相同的工作。
【讨论】:
没有来源?我自己google了一下:boost.org/doc/libs/1_55_0/doc/html/boost_lexical_cast/…【参考方案16】:我的问题:
-
独立于语言环境的字符串加倍(小数分隔符始终为“.”)
字符串转换失败时的错误检测
我的解决方案(使用 Windows 函数 _wcstod_l):
// string to convert. Note: decimal seperator is ',' here
std::wstring str = L"1,101";
// Use this for error detection
wchar_t* stopString;
// Create a locale for "C". Thus a '.' is expected as decimal separator
double dbl = _wcstod_l(str.c_str(), &stopString, _create_locale(LC_ALL, "C"));
if (wcslen(stopString) != 0)
// ... error handling ... we'll run into this because of the separator
HTH ... 我花了很长时间才找到这个解决方案。而且我仍然觉得我对字符串本地化和其他东西了解不够......
【讨论】:
以上是关于std::string 浮动或加倍的主要内容,如果未能解决你的问题,请参考以下文章