Boost :: Lexical_cast преобразование в данные с плавающей запятой

Я получаю данные из 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 поток, полученный из базы данных. Это проблема конверсии?

1

Решение

Проблема в том, что один раз вы рассматриваете разделенные токены как строки (оставляя их без изменений), а иногда вы конвертируете в 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)

0

Другие решения


По вопросам рекламы [email protected]