python - 解包十六进制编码的 float

标签 python c++ floating-point hex

我正在尝试将以下 Python 代码翻译成 C++:

import struct
import binascii


inputstring = ("0000003F" "0000803F" "AD10753F" "00000080")
num_vals = 4

for i in range(num_vals):
    rawhex = inputstring[i*8:(i*8)+8]

    # <f for little endian float
    val = struct.unpack("<f", binascii.unhexlify(rawhex))[0]
    print val

    # Output:
    # 0.5
    # 1.0
    # 0.957285702229
    # -0.0

因此它读取 32 位的十六进制编码字符串,使用 unhexlify 方法将其转换为字节数组,并将其解释为小端浮点值。

以下几乎可以工作,但代码有点糟糕(最后一个 00000080 解析不正确):

#include <sstream>
#include <iostream>


int main()
{
    // The hex-encoded string, and number of values are loaded from a file.
    // The num_vals might be wrong, so some basic error checking is needed.
    std::string inputstring = "0000003F" "0000803F" "AD10753F" "00000080";
    int num_vals = 4;


    std::istringstream ss(inputstring);

    for(unsigned int i = 0; i < num_vals; ++i)
    {
        char rawhex[8];

// The ifdef is wrong. It is not the way to detect endianness (it's
// always defined)
#ifdef BIG_ENDIAN
        rawhex[6] = ss.get();
        rawhex[7] = ss.get();

        rawhex[4] = ss.get();
        rawhex[5] = ss.get();

        rawhex[2] = ss.get();
        rawhex[3] = ss.get();

        rawhex[0] = ss.get();
        rawhex[1] = ss.get();
#else
        rawhex[0] = ss.get();
        rawhex[1] = ss.get();

        rawhex[2] = ss.get();
        rawhex[3] = ss.get();

        rawhex[4] = ss.get();
        rawhex[5] = ss.get();

        rawhex[6] = ss.get();
        rawhex[7] = ss.get();
#endif

        if(ss.good())
        {
            std::stringstream convert;
            convert << std::hex << rawhex;
            int32_t val;
            convert >> val;

            std::cerr << (*(float*)(&val)) << "\n";
        }
        else
        {
            std::ostringstream os;
            os << "Not enough values in LUT data. Found " << i;
            os << ". Expected " << num_vals;
            std::cerr << os.str() << std::endl;
            throw std::exception();
        }
    }
}

(在 OS X 10.7/gcc-4.2.1 上编译,使用简单的 g++ blah.cpp)

特别是,我想摆脱 BIG_ENDIAN 宏的东西,因为我确信有更好的方法来做到这一点,如 this post讨论。

很少有其他随机细节 - 我不能使用 Boost(对项目的依赖性太大)。该字符串通常包含 1536 (83*3) 和 98304 个浮点值 (323*3),最多 786432 (643>*3)

(edit2:添加了另一个值,00000080 == -0.0)

最佳答案

以下是您修改后的更新代码以删除 #ifdef BIG_ENDIAN block 。它使用一种应该与主机字节顺序无关的读取技术。它通过将十六进制字节(在您的源字符串中是小端)读入与 iostream std::hex 运算符兼容的大端字符串格式来实现这一点。一旦采用这种格式,主机字节顺序是什么就无关紧要了。

此外,它修复了 rawhex 在某些情况下需要以零终止才能插入到 convert 中而没有尾随垃圾的错误。

我没有大端系统可以测试,所以请在你的平台上验证。这是在 Cygwin 下编译和测试的。

#include <sstream>
#include <iostream>

int main()
{
    // The hex-encoded string, and number of values are loaded from a file.
    // The num_vals might be wrong, so some basic error checking is needed.
    std::string inputstring = "0000003F0000803FAD10753F00000080";
    int num_vals = 4;
    std::istringstream ss(inputstring);
    size_t const k_DataSize = sizeof(float);
    size_t const k_HexOctetLen = 2;

    for (uint32_t i = 0; i < num_vals; ++i)
    {
        char rawhex[k_DataSize * k_HexOctetLen + 1];

        // read little endian string into memory array
        for (uint32_t j=k_DataSize; (j > 0) && ss.good(); --j)
        {
            ss.read(rawhex + ((j-1) * k_HexOctetLen), k_HexOctetLen);
        }

        // terminate the string (needed for safe conversion)
        rawhex[k_DataSize * k_HexOctetLen] = 0;

        if (ss.good())
        {
            std::stringstream convert;
            convert << std::hex << rawhex;
            uint32_t val;
            convert >> val;

            std::cerr << (*(float*)(&val)) << "\n";
        }
        else
        {
            std::ostringstream os;
            os << "Not enough values in LUT data. Found " << i;
            os << ". Expected " << num_vals;
            std::cerr << os.str() << std::endl;
            throw std::exception();
        }
    }
}

关于python - 解包十六进制编码的 float ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10054314/

相关文章:

python - “无法访问 'sort_values' 对象的可调用属性 'DataFrameGroupBy',请尝试使用 'apply' 方法”

c++ - 使用 vector C++进行二进制搜索

c# - 如何在 C# 中将 Decimal 转换为 Double?

c++ - 比较float和float文字时的奇怪输出

c++ - ZeroMQ 在 context.close() 中被阻塞。如何在 C++ 中安全地关闭套接字和上下文?

更新后 Ruby Float#round 行为发生变化

python - 为什么我的 doctest 测试用例放在单独的文件中时会失败?

python - 如何将 URI 转换为字典

python - 将 IP 列表转换为相应 IP 范围的列表 (python)

c++ - SSE2 内在函数在哪里存储结果?