c++ - Boost::Lexical_cast 转换为 float 改变数据

标签 c++ boost floating-point 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。这正是我想要的。问题是,我有:

enter image description here

不知道从哪里来的。唯一的变化是 m_caracs 是从数据库接收的流。这是转换问题吗?

最佳答案

问题是,有一次您将拆分标记视为字符串(保持不变),有时您会转换为 float 。

转换为 float 会创建一个不精确的二进制浮点表示。

为避免这种情况,请不要使用二进制浮点表示法,而是使用具有足够精度的十进制表示法来准确存储您的十进制输入表示法。

使用,例如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是一个有效的 float (例如 lexical_cast )。此外,NaN 可能存在问题或 Inf

注意:在上面的示例中,您可能希望使用 qi::real_parser<Float, custom_real_policies<Float> >直接解析为 cpp_dec_float ,并且不识别指数(如 e54 )

关于c++ - Boost::Lexical_cast 转换为 float 改变数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28185258/

相关文章:

c++ - 无效异常展开导致的崩溃?

c++ - 检查另一个窗口是否关闭c++

c++ - boost::call_traits - 为什么 gcc 为此给出 false?

boost - 线程静态编译示例

c++ - 使用 Netbeans (linux/mac) 为 dylib 设置当前/兼容版本

c++ - 在 C++ Microsoft Visual Studio 2010 中调试多个环境变量

C++ boost asio Windows 文件句柄 a​​sync_read_until 无限循环 - 没有 eof

php - 浮点精度问题仅影响计算吗?

c - 为什么 float 会这样做?

java - Java中的浮点和 double 据类型