2010-04-28 1 views
3

У меня есть двоичный файл двойников, который мне нужно загрузить с помощью C++. Однако моя проблема заключается в том, что она была написана в формате большой буквы, но оператор fstream >> затем считывает число неправильно, потому что моя машина малозначительна. По-видимому, простая задача для решения целых чисел, но для парных и плавающих решений, которые я нашел, не будет работать. Как я могу (или должен ли я это исправить)?Почему байты с плавающей запятой отличаются от целочисленного байтового обмена?

Я прочитал это в качестве эталона для целых байтов свопинга:
How do I convert between big-endian and little-endian values in C++?

EDIT: Хотя эти ответы поучительно, я обнаружил, что моя проблема с самим файлом, а не формат двоичного файла данные. Я считаю, что мой байтовый обмен делает работу, я просто получаю запутывающие результаты. Спасибо за вашу помощь!

+0

я ожидал бы двойной/поплавок байт обменивать решения работать точно так же (то есть, определить поплавок/int32 союз, напишите неправильный обратный порядок байт поплавок в нем, байт-своп в int32, и читать поплавок снова), поэтому я думаю, вы должны объяснить, какие решения вы пытались, которые не будут работать. –

ответ

6

Самый переносимый способ состоит в сериализации в текстовом формате, так что у вас нет проблем с порядком байтов. Вот как работает operator>>, поэтому у вас не должно быть никаких проблем с версией >>. Основная проблема с бинарными форматами (что объясняет проблемы с эндиантами) состоит в том, что числа с плавающей запятой состоят из нескольких битов мантиссы, количества бит экспоненты и знакового бита. Показатель может использовать смещение. Это означает, что повторный порядок прямого байта может оказаться недостаточным, в зависимости от исходного и целевого формата.

Если вы используете и IEEE-754 на обеих машинах, тогда вы можете быть в порядке с обратным байтом, поскольку этот стандарт указывает формат обмена битовой строкой, который должен быть переносимым (проблемы с байтовым порядком в сторону).

Если вам нужно преобразовать между двумя машинными архитектурами, и вы должны использовать дамп памяти необработанного байта, то до тех пор, пока формат базового номера будет таким же (т.е. они имеют одинаковое количество бит в каждой части номера) , вы можете прочитать данные в массиве unsigned char, использовать некоторые базовые байтовые и битовые подкачки для исправления формата хранения, а затем скопировать необработанные байты в переменную соответствующего типа.

+0

Вам не нужно сериализоваться в текстовом формате - вы можете преобразовать число с плавающей запятой в три целых числа (знак, мантисса и экспонента), используя ориентированный на значение, а не ориентированный на представление метод, а затем сериализуйте эти целые числа в сетевой байт порядок в обычном порядке. – caf

+0

Мне любопытно: есть ли какие-либо чипы, не являющиеся основными, которые не IEEE-754? – Will

+0

@caf: вы можете пропустить шаг и преобразовать их в два значения: подписанная мантисса и экспонента. Но стандартный способ (де) сериализации в сетевом порядке байтов заслуживает ответа. – Potatoswatter

0

Стандартные операторы преобразования не работают с двоичными данными, поэтому неясно, как вы попали туда, где находитесь.

Однако, поскольку байтовая замена работает на байтах, а не на числах, вы выполняете ее на данных, предназначенных для плавания, как данные, которые будут целыми.

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

int32_t raw_bytes; 
stream >> raw_bytes; // not an int, just 32 bits of bytes 
my_byte_swap(raw_bytes); // swap 'em 
float f = * reinterpret_cast< float * >(& raw_bytes); // read them into FPU