Преобразовать три байта, два дополнения, целое число со знаком

В формате сейсмических данных SEG-D некоторые параметры заголовка форматируются как три байта, два дополнения, двоичный код со знаком. Все значения являются порядковыми номерами.

Используя String # unpack, ядро ​​Ruby может преобразовывать только 16-битные и 32-битные значения, но не 24-битные.

Как я могу получить двоичные значения, преобразованные в целые числа следующим образом:

"\x00\x00\x00" => 0x000000 (0)
"\x00\x00\x01" => 0x000001 (1)
"\x7F\xFF\xFF" => 0x7FFFFF (8388607)
"\xFF\xFF\xFF" => -0x000001 (-1)
"\x80\x00\x00" => -0x800000 (-8388608)

1 ответ

Решение

Преобразуйте первый байт в 8-разрядный со знаком (дополнение двух), а второй и третий - в 16-разрядный без знака.

# String to be converted (-8388608)
bin = "\x80\x00\x00"

# Convert as signed 8-bit and unsigned 16-bit (big-endian)
values = bin.unpack("c S>")

# Add with the first byte weighted
converted = values[0] * 2**16 + values[1]

Альтернативная версия последней строки с использованием побитовых операций shift и OR (возможно, более эффективной):

converted = values[0] << 16 | values[1]
Другие вопросы по тегам