Преобразование 16-разрядного целого числа в 32-разрядное с плавающей точкой - PullRequest
3 голосов
/ 12 августа 2011

Я пытаюсь перенести часть кода, написанного на другом языке (малоизвестный под названием Igor Pro от Wavemetrics для тех, кто о вас слышал), на Python.

В этом коде происходит преобразование типа данных из 16-разрядного целого числа (считанного из 16-разрядного двоичного файла с прямым порядком байтов) в 32-разрядное число с плавающей точкой одинарной точности. В этой программе преобразование выглядит следующим образом:

16-разрядное целое число со знаком:

print tmp
tmp[0]={-24160,18597,-24160,18597,-24160}

преобразовано в 32-битную с плавающей точкой:

Redimension/S/E=1 tmp
print tmp
tmp[0]={339213,339213,5.79801e-41,0,0}

Флаг / опция /S указывает, что тип данных tmp должен быть float32 вместо int16. Однако я считаю, что важным флагом / параметром является /E=1, который называется «Принудительное изменение формы без преобразования или перемещения данных».

В Python преобразование выглядит следующим образом:

>>> tmp[:5]
array([-24160,  18597, -24160,  18597, -24160], dtype=int16)

>>> tmp.astype('float32')
array([-24160.,  18597., -24160., ...,  18597., -24160.,  18597.], dtype=float32)

Это то, что я ожидаю, но мне нужно найти функцию / операцию, которая эмулирует опцию /E=1 в исходном коде выше. Есть ли очевидный способ конвертации -24160 и 18597 в 339213? Это как-то связано с byteswap или newbyteorder или чем-то еще?

Ответы [ 3 ]

5 голосов
/ 12 августа 2011
import numpy
tmp=numpy.array([-24160,18597,-24160,18597,-24160, 0], numpy.int16)
tmp.dtype = numpy.float32
print tmp

Результат:

[  3.39213000e+05   3.39213000e+05   5.79801253e-41]

Мне пришлось добавить ноль в список значений, потому что есть нечетное количество значений. Он не может интерпретировать их как 32-битные значения с плавающей запятой, поскольку существует 5 16-битных значений.

2 голосов
/ 12 августа 2011

Используйте просмотр вместо astype :

In [9]: tmp=np.array([-24160,  18597, -24160,  18597, -24160, 18597], dtype=int16)

In [10]: tmp.view('float32')
Out[10]: array([ 339213.,  339213.,  339213.], dtype=float32)
  1. .astype создает копию массива, приведенного к новому dtype
  2. .view возвращает представление массива (с теми же базовыми данными), с данными, интерпретированными в соответствии с новым dtype.
1 голос
/ 12 августа 2011

Есть ли очевидный способ, как -24160 и 18597 конвертируются в 339213?

Нет, но также нет никакого очевидного способа, которым -24160 конвертировал бы в 339213 и 5.79801e-41 и 0.

Похоже, преобразование требует двух входных чисел для создания одного вывода (возможно, путем объединения необработанных 2 × 16 битов в 32 бита и вызова результата как плавающего). В этом случае пара -24160,18597 постоянно становится 339213, а 5.79801e-41, вероятно, является результатом -24160,0, где 0 изобретен, потому что у нас заканчиваются входные данные. Поскольку 5.79801e-41 выглядит так, как будто это может быть денормаль с одинарной точностью, это означает, что два 16-битных блока, вероятно, объединены в порядке с прямым порядком байтов.

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

...