Improve floating point parser accuracy

I noticed something strange when comparing boost :: lexical_cast and parsing syntax. I am trying to parse a string in a float. for some reason, the spirit gives a very inaccurate result. for example: when parsing the string "219721.03839999999" using lexical_cast, I get 219721.03, which is more or less OK. but when I use the spirit (see code below), I get "219721.11", which is far from okay. Any idea why this is happening?

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; } 
+4
source share
1 answer

Thus, it will probably be a restriction / error of the parser of type "float". Try using the double_ parser.

 #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; } 

Output:
Qi :: double_: 219721,03839999999036
qi :: float_: 219721.109375

+5
source

Source: https://habr.com/ru/post/1488955/


All Articles