【问题标题】:Boost spirit floating number parser precision提升灵浮点数解析器精度
【发布时间】:2013-06-30 14:26:42
【问题描述】:

比较 boost::lexical_cast 和 boost 精神解析时,我注意到一些奇怪的东西。 我正在尝试将字符串解析为浮点数。由于某种原因,精神给出了非常不精确的结果。例如:当使用 lexical_cast 解析字符串“219721.03839999999”时,我得到 219721.03,这或多或少是可以的。但是当我使用精神(见下面的代码)时,我得到“219721.11”,这远非正常。知道为什么会这样吗?

template<>
inline float LexicalCastWithTag(const std::string& arg)
{
    float result = 0;

    if(arg.empty())
    {
        throw BadLexicalCast("Cannot convert from to std::string to float");
    }

    auto itBeg = arg.begin();
    auto itEnd = arg.end();

    if(!boost::spirit::qi::parse(itBeg, itEnd, boost::spirit::qi::float_, result) || itBeg != itEnd)
    {
        throw BadLexicalCast("Cannot convert from to std::string to float");
    }

    return result;
}

【问题讨论】:

  • 更具体地说,lexical_cast 为您提供正确的219721.03125,这是最接近219721.03839999999 的有效float,而qi::float_ 为您提供219721.109375,这确实没有看起来是对的。
  • 数字的整数部分几乎使容量饱和。在 qi::float_type::parse() 中计算结果的方式是,在“添加”每个小数复合时发生的“小”错误。事实上,这看起来像是一个错误,因为更智能的算法没有这种次优行为。
  • 我们如何将这个问题传达给精神维护者?
  • 我刚刚在spirit-general添加了我的 0.019999999552965164 美元
  • 正如刚刚在 [spirit-general] 邮件列表中宣布的,看起来这个错误已在下一个 boost 版本中得到修复:boost.2283326.n4.nabble.com/Symbol-table-tp4668838p4668842.html /cc @G.Civardi

标签: c++ boost-spirit lexical-cast


【解决方案1】:

所以它可能是“浮动”类型解析器的限制/错误。尝试使用double_解析器。

#include<iostream>
#include<iomanip>
#include<string>
#include<boost/spirit/include/qi.hpp>

int main()
{
    std::cout.precision(20);

    //float x=219721.03839999999f;  
    //std::cout << x*1.0f << std::endl;  
    //gives 219721.03125  

    double resultD;
    std::string arg="219721.03839999999";

    auto itBeg = arg.begin();
    auto itEnd = arg.end();
    if(!boost::spirit::qi::parse(itBeg, itEnd,boost::spirit::qi::double_,resultD) || itBeg != itEnd)
        std::cerr << "Cannot convert from std::string to double" << std::endl;
    else
        std::cout << "qi::double_:" << resultD << std::endl;

    float resultF;
    itBeg = arg.begin();
    itEnd = arg.end();
    if(!boost::spirit::qi::parse(itBeg, itEnd,boost::spirit::qi::float_,resultF) || itBeg != itEnd)
        std::cerr << "Cannot convert from std::string to float" << std::endl;
    else
        std::cout << "qi::float_ :" << resultF << std::endl;

    return 0;
}

输出:
qi::double_:219721.03839999999036
qi::float_:219721.109375

【讨论】:

  • 看起来很合理,我已经解析成双精度然后只是将返回值转换为浮点数,就像一个魅力:)
  • 我认为你可以在解析器中传递一个浮点变量,向下转换将由解析器完成。
  • 还有另一种完成事情的可能性,但是,我更愿意控制我的变量发生的事情。如您所见,没有人可以信任:)
  • 这是非常务实的观点,除非您可以完全使用双重表示 :-)
  • 我不能,这是我的词汇转换的想法。在某些情况下,您希望转换为双精度,而在某些情况下您更喜欢浮动。特别是当我们谈论我们在内存中保存的数千万个结构时,每一位都很重要
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-21
  • 1970-01-01
  • 2012-02-28
  • 1970-01-01
  • 2022-11-19
相关资源
最近更新 更多