Распаковка шестнадцатеричных чисел с плавающей запятой

Я пытаюсь перевести следующий код 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]

    # 

Итак, он считывает 32-битную строку в шестнадцатеричном коде и превращает ее в массив байтов с помощью метода unhexlifyи интерпретирует его как значение с плавающей запятой с прямым порядком байтов.

Следующее почти работает, но код какой-то дрянной (и последний 00000080разбирает неправильно):

#include 
#include 


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, так как я уверен, что есть более приятный способ сделать это, так как этот постобсуждает.

Несколько других случайных подробностей — я не могу использовать Boost (слишком большая зависимость для проекта). Строка обычно содержит от 1536 (8 3*3) до 98304 значений с плавающей запятой (32 3*3), не более 786432 (64 3*3 )

(edit2: добавлено другое значение, 00000080== -0.0)

6
задан dbr 12 April 2012 в 11:21
поделиться