Я получаю данные из MySQL и пытаюсь поиграть с ними. Полученные данные находятся в m_caracs
а потом я пытаюсь вырезать каждую часть этого потока в другом float
,
Давайте посмотрим код:
#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>
#include <iostream>
#include <vector>
#include <string>
std::string m_sten;
std::string m_feal;
std::string m_felt;
std::string m_inte;
std::string m_sag;
std::string m_ende;
std::string m_asko;
std::string m_vit;
void test(bool mon)
{
std::string m_caracs = "f21.0i51.24v58.65c47.3s5.54d57.68e54.23h24.42";
if (mon == 0)
{
std::vector<std::string> charmps;
boost::split(charmps, m_caracs, boost::is_any_of("fivcsdeh"));
m_sten = boost::lexical_cast<float>(charmps[1]);
m_feal = boost::lexical_cast<float>(charmps[2]);
m_felt = boost::lexical_cast<float>(charmps[3]);
m_inte = boost::lexical_cast<float>(charmps[4]);
m_sag = boost::lexical_cast<float>(charmps[5]);
m_ende = boost::lexical_cast<float>(charmps[6]);
m_asko = boost::lexical_cast<float>(charmps[7]);
m_vit = boost::lexical_cast<float>(charmps[8]);
std::cout << m_caracs << std::endl;
}
else
{
std::cout << m_caracs << std::endl;
m_caracs = "f" + boost::lexical_cast<std::string>(m_sten) +
"i" + boost::lexical_cast<std::string>(m_feal) +
"v" + boost::lexical_cast<std::string>(m_felt) +
"c" + boost::lexical_cast<std::string>(m_inte) +
"s" + boost::lexical_cast<std::string>(m_sag) +
"d" + boost::lexical_cast<std::string>(m_ende) +
"e" + boost::lexical_cast<std::string>(m_asko) +
"h" + boost::lexical_cast<std::string>(m_vit);
std::cout << m_caracs << std::endl;
}
}
int main()
{
test(1);
test(0);
}
Ты это видишь f21.0i51.24v58.65c47.3s5.54d57.68e54.23h24.42
становится f21.0i51.24v58.65c47.3s5.54d57.68e54.23h24.42
, Это именно то, что я хочу. Проблема в том, что у меня есть:
Я не знаю, откуда это. Единственное изменение заключается в том, что m_caracs
поток, полученный из базы данных. Это проблема конверсии?
Проблема в том, что один раз вы рассматриваете разделенные токены как строки (оставляя их без изменений), а иногда вы конвертируете в float.
Преобразование в float создает неточный двоичное представление с плавающей точкой.
Чтобы избежать этого, не используйте двоичное представление с плавающей запятой, но используйте десятичное представление с достаточной точностью, чтобы точно сохранить ваше десятичное входное представление.
Используйте, например, boost::multiprecision::cpp_dec_float
#include <boost/spirit/include/qi.hpp>
#include <boost/multiprecision/cpp_dec_float.hpp>
#include <iostream>
namespace qi = boost::spirit::qi;
typedef boost::multiprecision::cpp_dec_float_50 Float;
int main()
{
std::string const m_caracs("f21.0i51.24v58.65c47.3s5.54d57.68e54.23h24.42");
std::cout << m_caracs << '\n';
Float m_sten, m_feal, m_felt, m_inte, m_sag, m_ende, m_asko, m_vit;
//auto num = qi::as_string[qi::raw[qi::double_]]; // this would parse exponents like 57.68e54
auto num = boost::proto::deep_copy(qi::as_string[+qi::char_("-+0-9.")]);
if (qi::parse(m_caracs.begin(), m_caracs.end(),
'f' >> num >> 'i' >> num >> 'v' >> num >>
'c' >> num >> 's' >> num >> 'd' >> num >>
'e' >> num >> 'h' >> num,
m_sten, m_feal, m_felt, m_inte, m_sag, m_ende, m_asko, m_vit
))
{
std::cout <<
'f' << m_sten <<
'i' << m_feal <<
'v' << m_felt <<
'c' << m_inte <<
's' << m_sag <<
'd' << m_ende <<
"e" << m_asko <<
'h' << m_vit << '\n';
}
}
PS Обратите внимание, что есть также проблема с форматом ввода! 57.68e54
является действительным числом с плавающей запятой (например, для lexical_cast
). Кроме того, могут быть проблемы с NaN
или же Inf
Примечание: в приведенном выше примере вы, вероятно, захотите использовать qi::real_parser<Float, custom_real_policies<Float> >
разобрать прямо в cpp_dec_float
и не признавая показатель (как e54
)