的boost :: lexical_cast的转换为浮动变化的数据 [英] Boost::Lexical_cast conversion to float changes data

查看:194
本文介绍了的boost :: lexical_cast的转换为浮动变化的数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我从MySQL接收数据,并尝试用它来播放。接收到的数据是 m_caracs 然后我试图削减该流在其他浮动的各个子部分

I am receiving data from MySQL and try to play with it. The data received is in m_caracs and then I try to cut every sub-parts of this stream in other float.

让我们来看看code:

Let's see the code :

#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 。这正是我想要的。问题是,我有:

You can see that f21.0i51.24v58.65c47.3s5.54d57.68e54.23h24.42 becomes f21.0i51.24v58.65c47.3s5.54d57.68e54.23h24.42. This is exactly what I want. The problem is, I have that :

我不知道它从何而来。唯一的变化是, m_caracs 是从数据库中获得的流。那是一个转换的问题?

I don't know where it comes from. The only change is that m_caracs is a stream received from a database. Is that a conversion problem ?

推荐答案

现在的问题是,有一次你把分割标记字符串(让他们保持不变),有时你转换为浮动。

The problem is that one time you treat the split tokens as strings (leaving them unchanged), and sometimes you convert to float.

浮动转换创建的不精确的二进制浮点重新presentation。

The conversion to float creates an inexact binary floating point representation.

要避免它,不使用二进制浮点重新presentation,但使用一个小数重新presentation有足够的precision准确地存储您重新presentation十进制输入。

To avoid it, don't use a binary floating point representation, but use a decimal representation with sufficient precision to accurately store your decimal input representation.

使用,例如的boost ::多precision :: cpp_dec_float

<大骨节病> 住在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的天道酬勤

PS Note there is also a problem with the input format! 57.68e54 is a valid floating point number (e.g. for lexical_cast). Also, there could be issues with NaN or Inf

注:上面你可能想使用齐:: real_parser&LT的例子;浮动,custom_real_policies&LT;浮球GT; &GT; 直接解析成 cpp_dec_float ,并没有认识到像 E54指数(

Note: in the example above you'd probably want to use qi::real_parser<Float, custom_real_policies<Float> > to parse directly into a cpp_dec_float, and not recognizing an exponent (like e54)

这篇关于的boost :: lexical_cast的转换为浮动变化的数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆