Skip to content

NumPy - Byte Swapping

Computer memory stores multi-byte data types (like integers or floats) using a specific byte order, known as endianness. This refers to the sequence in which bytes are arranged in memory.

  • Little-endian: The least significant byte (LSB) is stored at the smallest memory address.
  • Big-endian: The most significant byte (MSB) is stored at the smallest memory address.

Most modern processors (like Intel x86/x64) are little-endian, while others (some older architectures, network byte order) are big-endian. When sharing binary data between systems with different endianness, or reading data from files with a specific byte order, you might need to swap the byte order.

NumPy provides the ndarray.byteswap() method to toggle the byte order of the array’s data between little-endian and big-endian representations.

ndarray.byteswap(inplace=False)

Parameter:

  • inplace: If True, the byte swapping is performed directly on the array’s data (in-place). If False (default), it returns a new array with the bytes swapped, leaving the original array unchanged.

Let’s illustrate with an example using 16-bit integers (np.int16), which occupy 2 bytes:

import numpy as np
# Create an array of 16-bit integers
# 1 = 0x0001, 256 = 0x0100, 8755 = 0x2233
a = np.array([1, 256, 8755], dtype=np.int16)
print(f"Original array: {a}")
# Display hexadecimal representation (assuming little-endian machine)
# On little-endian: 1 -> 01 00, 256 -> 00 01, 8755 -> 33 22
print(f"Hex representation (native): {[hex(x) for x in a]}")
print(f"Raw bytes (native endian): {a.tobytes().hex(' ')}")
# Swap bytes IN-PLACE
print("\nApplying byteswap(inplace=True)...")
a.byteswap(inplace=True)
print(f"Array after in-place byteswap: {a}")
# Swapped values: 0x0100 = 256, 0x0001 = 1, 0x3322 = 13090
print(f"Hex representation (swapped): {[hex(x) for x in a]}")
print(f"Raw bytes (swapped endian): {a.tobytes().hex(' ')}")
# Swap bytes and return a NEW array (original 'a' remains swapped)
print("\nApplying byteswap(inplace=False) on the already swapped array...")
b = a.byteswap(inplace=False) # Swaps back to original byte order
print(f"Original array 'a' (still swapped): {a}")
print(f"New array 'b' (swapped back): {b}")
print(f"Raw bytes of 'b': {b.tobytes().hex(' ')}")

Expected output (exact hex values depend on system endianness, this assumes little-endian):

Original array: [ 1 256 8755]
Hex representation (native): ['0x1', '0x100', '0x2233']
Raw bytes (native endian): 01 00 00 01 33 22
Applying byteswap(inplace=True)...
Array after in-place byteswap: [ 256 1 13090]
Hex representation (swapped): ['0x100', '0x1', '0x3322']
Raw bytes (swapped endian): 00 01 01 00 22 33
Applying byteswap(inplace=False) on the already swapped array...
Original array 'a' (still swapped): [ 256 1 13090]
New array 'b' (swapped back): [ 1 256 8755]
Raw bytes of 'b': 01 00 00 01 33 22

Application: Byte swapping is crucial when reading/writing binary files generated on systems with different endianness, or when dealing with certain network protocols or hardware interfaces.

For more details, see the ndarray.byteswap documentation and information on Byte Swapping in NumPy.