gpt4 book ai didi

c++ - boost::spirit 和 strict_real_policies 无法解析太长的整数

转载 作者:行者123 更新时间:2023-11-30 04:54:48 25 4
gpt4 key购买 nike

我必须处理文本格式的非常长的整数——长到无法放入 32 位整数。我需要将这样的文本解析成

boost::variant<int, double>.

因此,如果对于一个整数来说有一个长整数到大整数,它需要进入 double 。请参见下面的示例。它不解析名称值对

MUESR1 = 411100000000000. 

如何解决这个问题?

#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/include/std_pair.hpp>
#include <iterator>


namespace qi = boost::spirit::qi;
namespace spirit = boost::spirit;
namespace ascii = boost::spirit::ascii;

typedef boost::variant<int, double> VALUE;
typedef std::pair<std::string, VALUE> PAIR;
typedef std::map<std::string, VALUE> PAIRS;
template<typename Iterator>
struct parameters:qi::grammar<Iterator, PAIRS(), ascii::space_type>
{
qi::rule<Iterator, std::string(), ascii::space_type> m_sName;
qi::rule<Iterator, VALUE(), ascii::space_type> m_sValue;
qi::rule<Iterator, PAIR(), ascii::space_type> m_sNameValue;
qi::rule<Iterator, PAIRS(), ascii::space_type> m_sRoot;
qi::real_parser<double, qi::strict_real_policies<double> > m_sReal;

parameters(void)
:parameters::base_type(m_sRoot)
{ m_sName %= qi::lexeme[qi::char_("a-zA-Z_") >> *qi::char_("a-zA-z_0-9")];
m_sValue %= m_sReal | spirit::int_;
m_sNameValue %= m_sName >> qi::lit('=') >> m_sValue >> -qi::lit('\n');
m_sRoot %= m_sNameValue >> *m_sNameValue;
}
};


int main(int, char**)
{
static const char s_ap[] = "\
MUEPH1 = 7.014158 MUEPHW= -0.3 MUEPWP = 0.23 MUEPHL= -0.72 MUEPLP = 3.4 MUEPHS = 2.976E-07 MUEPSP = 5 VTMP= -1.8463 WVTH0= -1.01558 MUESR0 = 0.01256478438899837 MUESR1 = 411100000000000\n\
MUEPHW2 = 0 MUEPWP2 = 1\n";
parameters<const char*> sGrammar;
const char *pIter = s_ap;
const char *const pEnd = s_ap + sizeof s_ap - 1;
PAIRS sValues;
if (phrase_parse(pIter, pEnd, sGrammar, boost::spirit::ascii::space, sValues) && pIter == pEnd)
{ std::cerr << "parsing successful!" << std::endl;
for (const auto &r : sValues)
std::cout << r.first << "=" << std::scientific << r.second << std::endl;
}
else
{ std::cerr << "parsing failed!" << std::endl;
std::cerr << pIter << std::endl;
}
}

最佳答案

是的,语法只要求解析严格的实数。如果您不想这样,则需要接受其他实数。 @llonesmiz 的评论是一种方法。

Alternatively, it seems like you could just parse doubles. Though binary real representation can be "lossy" that doesn't happen for the integral part of the mantissa until you exceed the 52/53 bits of significand (https://en.wikipedia.org/wiki/Double-precision_floating-point_format). By comparison, popular compilers have int at 32 bits.

Live On Coliru

//#define BOOST_SPIRIT_DEBUG
#include <boost/fusion/include/std_pair.hpp>
#include <boost/spirit/include/qi.hpp>
#include <iterator>
#include <iomanip>

namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;

typedef boost::variant<int, double> VALUE;
typedef std::pair<std::string, VALUE> PAIR;
typedef std::map<std::string, VALUE> PAIRS;

template <typename Iterator> struct parameters : qi::grammar<Iterator, PAIRS(), ascii::space_type> {

parameters(void) : parameters::base_type(m_sRoot) {
m_sName = qi::lexeme[qi::char_("a-zA-Z_") >> *qi::char_("a-zA-z_0-9")];
m_sValue = m_sReal | qi::int_ | qi::double_;
m_sNameValue = m_sName >> '=' >> m_sValue >> -qi::lit('\n');
m_sRoot = m_sNameValue >> *m_sNameValue;

BOOST_SPIRIT_DEBUG_NODES((m_sName)(m_sValue)(m_sNameValue)(m_sRoot))
}

private:
qi::rule<Iterator, std::string(), ascii::space_type> m_sName;
qi::rule<Iterator, VALUE(), ascii::space_type> m_sValue;
qi::rule<Iterator, PAIR(), ascii::space_type> m_sNameValue;
qi::rule<Iterator, PAIRS(), ascii::space_type> m_sRoot;
qi::real_parser<double, qi::strict_real_policies<double> > m_sReal;
};

int main(int, char **) {
static const char s_ap[] = R"(
MUEPH1 = 7.014158 MUEPHW= -0.3 MUEPWP = 0.23 MUEPHL= -0.72 MUEPLP = 3.4 MUEPHS = 2.976E-07 MUEPSP = 5 VTMP= -1.8463 WVTH0= -1.01558 MUESR0 = 0.01256478438899837 MUESR1 = 411100000000000
MUEPHW2 = 0 MUEPWP2 = 1
)";

parameters<const char*> sGrammar;

const char *pIter = std::begin(s_ap);
const char *const pEnd = std::end(s_ap) - 1;
PAIRS sValues;

if (phrase_parse(pIter, pEnd, sGrammar, boost::spirit::ascii::space, sValues) && pIter == pEnd) {
std::cerr << "parsing successful!" << std::endl;
for (const auto &r : sValues)
std::cout << r.first << "=" << std::scientific << std::setprecision(2) << r.second << std::endl;
} else {
std::cerr << "parsing failed!" << std::endl;
std::cerr << std::quoted(std::string(pIter, pEnd)) << std::endl;
}
}

另请注意常规改进,例如向您的规则添加调试。

关于c++ - boost::spirit 和 strict_real_policies 无法解析太长的整数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53400077/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com