浮点数 <-> 字符串转换的替代方案?

8
有没有替代atofstrtodlexical_caststringstream或者sprintf的方法?
即:
  1. 快速
  2. C++风格(使用std::string而非char*
  3. 安全(无缓冲区溢出风险)
  4. 有效(若转换失败则返回NaN)
  5. 无需外部库(独立)
我更喜欢像这个一样的简单函数,它经过优化且精准。
原因:
  • atofstrtod是C函数,转换失败时不会返回NaN。我更喜欢在std::string上工作,所以我只是想问一下是否已经有人为std::string编写了包装器,我可以使用(如果您不介意的话)。
  • lexical_cast有Boost依赖性
  • stringstream很慢
  • sprintf存在缓冲区溢出风险且为C函数

5
建议您解释一下为什么排除了标准方法。如果您随意舍弃了所有最好的方法(明知您可以将atof封装在一个友好的std::string函数中),那么提出建议也毫无意义。 - tenfour
3
你正在将浮点数转换为字符串并担心性能?你有什么应用程序(不是合成基准测试),可以让你甚至注意到stringstream很“慢”吗? - Nemo
我正在编写一个库(或包装器),以便它可以用于任何事情,但是在合成基准测试中速度较慢。 - uray
使用strtod(string.c_str(), NULL)asprintf可以避免缓冲区溢出问题。公正地说,如果C函数能够解决你的问题,我找不到任何真正好的理由避免在C++中使用它们。 - zneak
@zneak:如果转换不成功,它不会返回NaN。 - uray
显示剩余2条评论
3个回答

1
我会看一下 Boost Spirit。

至少在格式化程序的基准测试中(即浮点数 -> 字符串),结果始终是最佳的。

此外,可以使用策略类非常好地配置解析时的确切输入格式规范和语义。


这是我绝对最小化依赖使用qi::any_real_parser<>的代码,以及它所涉及到的依赖列表:

#include <boost/spirit/include/qi_real.hpp>

namespace qi = boost::spirit::qi;

int main()
{
    const char input[] = "3.1415926";
    const char *f(input);
    const char *l(f+strlen(input));

    qi::any_real_parser<double> x;
    double parsed;
    x.parse(f, l, qi::unused, qi::unused, parsed);

    return 0;
}

  • boost/concept
  • boost/config
  • boost/detail
  • boost/exception
  • boost/fusion
  • boost/iterator
  • boost/math
  • boost/mpl
  • boost/optional
  • boost/preprocessor
  • boost/proto
  • boost/range
  • boost/regex
  • boost/spirit
  • boost/typeof
  • boost/type_traits
  • boost/utility
  • boost/variant

aligned_storage.hpp,assert.hpp,blank_fwd.hpp,blank.hpp,call_traits.hpp,checked_delete.hpp,concept_check.hpp,config.hpp,cstdint.hpp,current_function.hpp,foreach_fwd.hpp,foreach.hpp,get_pointer.hpp,implicit_cast.hpp,iterator.hpp,limits.hpp,math_fwd.hpp,next_prior.hpp,noncopyable.hpp,none.hpp,none_t.hpp,optional.hpp,ref.hpp,static_assert.hpp,swap.hpp,throw_exception.hpp,type.hpp,utility.hpp,variant.hpp,version.hpp

1 例如 http://www.boost.org/doc/libs/1_47_0/libs/spirit/doc/html/spirit/karma/performance_measurements/numeric_performance/double_performance.html


我可以在没有Boost依赖的情况下使用它吗? - uray
boost 依赖是什么?显然,你需要 boost/spirit/include/qi.hpp。但它只是一个头文件。它可能会引入 mpl 和 fusion 的一些部分。所以如果你的意思是这个,那么当然不能没有它使用。 - sehe
@uray:我不明白有关boost依赖的问题在哪里。假设你想出了另一个所需功能的库Q,那么显然你将依赖于库Q。您已经列举了所有标准库中可用的选项。如果问题是boost太大了,那么现在有一些工具可以提取你需要的部分。(例如 bcp) - Billy ONeal
我只是在寻求替代方案,如果没有其他选择,我更倾向于不向我的库中添加另一个依赖库。如果没有其他选择,我可以使用boost或者创建自己的包装器来使用现有的标准库。 - uray
在这种情况下,自己编写或使用strtod :) - sehe

1
如果你想要将数字类型转换为std::string,最新标准中有一个std::to_string函数可用。
不幸的是,最近我发现在Visual Studio 2010中,它有些受限,因为只有三个重载可用;long double、long long和unsigned long long。这导致在尝试从模板内部使用它们时会出现问题。

0

快速格式化库应该能够完成你所需要的转换,至少可以将浮点数写出。但是它不处理浮点数的解析。


嗯...它不能处理浮点数的解析:_) 我也查了一下那个库,因为我希望他们现在已经支持。没戏。 - sehe
@sehe:我在我的答案中已经注意到了这一点。 - Billy ONeal
没关系,我有点忽略了他还想要格式。我应该也把链接放进去的 :) - sehe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接