C++ Boost spirit浮点数解析器精度

C++ Boost spirit浮点数解析器精度,c++,boost-spirit,lexical-cast,C++,Boost Spirit,Lexical Cast,在比较boost::lexical_cast和boost-spirit解析时,我注意到了一些奇怪的事情。 我正在尝试将字符串解析为float。由于某种原因,spirit给出的结果非常不精确。例如:当使用词法转换解析字符串“219721.0383999999”时,我得到了219721.03,这或多或少是正常的。但当我使用spirit(见下面的代码)时,我得到了“219721.11”,这远远不够好。知道为什么会这样吗 template<> inline float LexicalCast

在比较boost::lexical_cast和boost-spirit解析时,我注意到了一些奇怪的事情。 我正在尝试将字符串解析为float。由于某种原因,spirit给出的结果非常不精确。例如:当使用词法转换解析字符串“219721.0383999999”时,我得到了219721.03,这或多或少是正常的。但当我使用spirit(见下面的代码)时,我得到了“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;
}
模板
内联浮点LexicalCastWithTag(const std::string和arg)
{
浮动结果=0;
if(arg.empty())
{
抛出BadLexicalCast(“无法从转换为标准::字符串到浮点”);
}
auto-itBeg=arg.begin();
auto itEnd=arg.end();
如果(!boost::spirit::qi::parse(itBeg,itEnd,boost::spirit::qi::float,result)| itBeg!=itEnd)
{
抛出BadLexicalCast(“无法从转换为标准::字符串到浮点”);
}
返回结果;
}

所以这可能是“float”类型解析器的局限性/缺陷。尝试使用双语法分析器

#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;
}
#包括
#包括
#包括
#包括
int main()
{
标准:计算精度(20);
//浮点数x=219721.0383999999F;

//std::cout更具体地说,词法转换为您提供了正确的
219721.03125
,这是最接近
219721.0383999999
的有效
float
,而
qi::float
为您提供了
219721.109375
,这似乎确实不正确。数字的整数部分几乎使容量饱和结果在qi::float_type::parse()中计算是这样的,在“添加”每个分数位数复合词时出现的“小”错误。事实上,这看起来像一个错误,因为更智能的算法没有这种次优的行为。我们如何将这个问题传达给spirit维护人员?我刚刚在[spirit general]上宣布,在上添加了我的$0.01999999552965164邮件列表,看起来这个bug已经在下一个boost版本中修复了:/cc@G.Civardilooks合理,我已经解析为double,然后将返回值转换为float,工作起来很有魅力:)我想你可以在解析器中传递一个float变量,向下转换将由解析器完成。还有一种可能得到这个东西完成了,但是,我更愿意控制我的变量发生的事情。正如你所看到的,没有人可以信任:)这是非常务实的观点,除非你可以完全使用双重表示:-)我不能,这是我词汇转换的想法。有些情况下你想转换为双重,有些情况下你更喜欢浮动。特别是当我们谈论我们在内存中保存的数千万个结构时,每一位都很重要