2015-01-28 2 views
1

Я получаю данные от MySQL и пытаюсь поиграть с ним. Полученные данные находятся в m_caracs, а затем я пытаюсь разрезать каждую часть этого потока в другом float.Boost :: Преобразование Lexical_cast в 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.42f21.0i51.24v58.65c47.3s5.54d57.68e54.23h24.42 становится. Это именно то, чего я хочу. Проблема заключается в том, что у меня есть:

enter image description here

Я не знаю, откуда приходит. Единственное изменение заключается в том, что m_caracs - это поток, полученный из базы данных. Это проблема конверсии?

+0

Я думаю, что ваш globals 'm_ *' должно быть 'floats' (и вы хотели вызвать' test (0) 'before' test (1) ') – sehe

+0

Oups, забыл редактировать, они извините. Сейчас я читаю ваш код. Благодарю вас. – Marion

ответ

0

Проблема заключается в том, что один раз вы обрабатываете раздвоенные жетоны как строки (оставляя их неизменными), а иногда вы конвертируете в float.

Преобразование в float создает inexact двоичное представление с плавающей запятой.

Чтобы избежать этого, не используйте двоичное представление с плавающей запятой, но используйте десятичное представление с достаточной точностью, чтобы точно хранить десятичное входное представление.

Использовать, например. boost::multiprecision::cpp_dec_float

Live On Coliru

#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

Ну, похоже, хорошо работает, но я поступил неправильно: мне просто нужно работать с целым числом ... Итак, хорошо, хватайся, чтобы снова заглянуть за тобой. Надеюсь, это поможет кому-то! – Marion

 Смежные вопросы

  • Нет связанных вопросов^_^