Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Общие вопросы > HexToSingle


Автор: sevlad 10.1.2007, 23:18
столкнулся с проблемой, что при чтении из файла в массив типа Char или Byte и последующей его обработкой необходимо преобразовать 4 последовательных байта в single. Бъюсь 4 дня. Знаю, что должно быть просто но ... smile  Пробывал record с двумя параметрами, первый word, второй single, на основе которого создавал массив и, что интересно, вроде структура должна занимать 6 байт в памяти, а показывает, что 8. Из-за этого собственно все и началось. При чтении данных по 2 (word) и 4 (single) байта все преобразуется правильно. smile 

Автор: Snowy 10.1.2007, 23:40
Код

var
  ba: array[0..3] of byte;
  s:  single;
begin
  ...
  s := ba[3] + ba[2] shl 8 + ba[1] shl 16 + ba[0] shl 24;


Добавлено @ 23:42 
Цитата(sevlad @  10.1.2007,  23:18 Найти цитируемый пост)
вроде структура должна занимать 6 байт в памяти, а показывает, что 8
Это из-за выравнивания. Чтобы его не было, нужно использовать packed record.

Автор: Beltar 11.1.2007, 09:40
2 Snowy:

Хм-м. А что происходит если к байту применить сдвиг на 16 или 24 бит?

Однажды мне понадобилось слеплять Float aka Single из приходящего с девайса потока байтов по протоколу ModBus в котором вещественное представляется с перестановкой байтов. Кажется это формат процессоров Motorola.
Я не мудрствуя лукаво сделал так. smile

Код

function ModBusByteToFloat(m:Mas4Bytes):Single;
var pRes:Pointer;
begin
pRes:=@Result;
PByte(pRes)^:=m[2];
PByte(Integer(pRes)+1)^:=m[1];
PByte(Integer(pRes)+2)^:=m[4];
PByte(Integer(pRes)+3)^:=m[3];
end;

Автор: Snowy 11.1.2007, 11:20
Тоже вариант.
Но наиболее быстрым тут будет вариантный packed record
Код
MyRec = packed record
  case integer of:
    0: ba: array[0..3] of byte;
    1: s:    single;
  end;

Автор: Beltar 11.1.2007, 12:42
Это да, у меня немного более сложный случай, кстати, мой тогдашний начальник такую задачу в свое время решал на ассемблере. smile 
Кстати, здесь старинный китайский вопрос может возникнуть "анахуа?"

Если байты уже лежат как нужно, то что мешает:
Код

var s:Single;
//...
FileStream.Read(S,4);


Тут надо сам алгоритм смотреть, вдруг там можно и без массива обойтись. smile

Автор: sevlad 11.1.2007, 22:13
Спасибо за подсказки.

Цитата(Snowy @  10.1.2007,  23:40 Найти цитируемый пост)
Это из-за выравнивания. Чтобы его не было, нужно использовать packed record. 

Это я понял. как опробую поделюсь.

А насчет

Цитата(Beltar @  11.1.2007,  12:42 Найти цитируемый пост)
Кстати, здесь старинный китайский вопрос может возникнуть "анахуа?"


да, все лежит как надо, и в случае побатного считывания проблем нет, но файл более 200 метров и время уходит ~10 мин на обработку одного параметра, а их там ~700, а надо ~ 10-20 сек. Так вот.

Автор: sevlad 12.1.2007, 20:42
Спасибо всем за помощь. smile 
В итоге получилось так:
Код

type ParamFloat=packed record
  Index:word;
  Value:single;
end;

****************************

var
CurParamFloat: array[1..50000] of ParamFloat;

****************************

BlockRead(InputFile,CurParamFloat,300000);


Хотелось бы читать все в динамический массив, но пока увы.

Отдельное спасибо Snowy 
Совет про paked record оказался правильным.

Итог: время обработки 200 метрового файла по одному параметру составляет 7 секунд. Приемлимо.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)