Skip to content

Instantly share code, notes, and snippets.

@sunsided
Created April 14, 2017 12:37
Show Gist options
  • Save sunsided/946455baffb03237a2270fd3f72786c9 to your computer and use it in GitHub Desktop.
Save sunsided/946455baffb03237a2270fd3f72786c9 to your computer and use it in GitHub Desktop.
Packing an array of IEEE 754 single-precision floats into a string of bytes in Python
import argparse
import struct
import binascii
from base64 import b64encode
from typing import Union, Iterable
def main():
parser = argparse.ArgumentParser()
parser.add_argument('number', type=float, nargs='+', help='The number to convert.')
args = parser.parse_args()
values = args.number
print('Converting {}'.format(values))
print('Single precision:')
print(' native: {}'.format(decode_native(values, type='f')))
print(' little endian: {}'.format(decode_little_endian(values, type='f')))
print(' big endian: {}'.format(decode_big_endian(values, type='f')))
print(' Intel format shell: BinData(128, "{}")'.format(
b64encode(decode_little_endian(values, type='f', hex=False)).decode()))
print('Double precision:')
print(' native: {}'.format(decode_native(values, type='d')))
print(' little endian: {}'.format(decode_little_endian(values, type='d')))
print(' big endian: {}'.format(decode_big_endian(values, type='d')))
print(' Intel format shell: BinData(128, "{}")'.format(
b64encode(decode_little_endian(values, type='d', hex=False)).decode()))
def decode_native(value: Union[float, Iterable[float]], type: str='f', hex: bool=True) -> Union[bytearray, str]:
if not hasattr(value, '__iter__'):
value = [value]
result = b''
for v in value:
result += struct.pack("@" + type, v)
ba = bytearray(result)
return ba if not hex else binascii.hexlify(ba).decode()
def decode_little_endian(value: Union[float, Iterable[float]], type: str='f', hex: bool=True) -> Union[bytearray, str]:
if not hasattr(value, '__iter__'):
value = [value]
result = b''
for v in value:
ba = struct.pack("@" + type, v)
decoded, = struct.unpack("<" + type, ba)
result += struct.pack("@" + type, decoded)
ba = bytearray(result)
return ba if not hex else binascii.hexlify(ba).decode()
def decode_big_endian(value: Union[float, Iterable[float]], type: str='f', hex: bool=True) -> Union[bytearray, str]:
if not hasattr(value, '__iter__'):
value = [value]
result = b''
for v in value:
ba = struct.pack("@" + type, v)
decoded, = struct.unpack(">" + type, ba)
result += struct.pack("@" + type, decoded)
ba = bytearray(result)
return ba if not hex else binascii.hexlify(ba).decode()
if __name__ == '__main__':
main()
@sunsided
Copy link
Author

Note that decoding a byte array to an array of floats can be done faster using

import array
float_array = array.array('f', byte_array)

# You might need to adjust for endianness
import sys
if sys.byteorder != 'little:
    arr.byteswap()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment