This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from typing import Literal | |
def unsigned_to_bytes(num: int, byteorder: Literal['big', 'little'] = 'big') -> bytes: | |
""" | |
convert an unsigned int to the least number of bytes as possible. | |
""" | |
# (0).bit_length() == 0 | |
return num.to_bytes((num.bit_length() + 7) // 8 or 1, byteorder) | |
def int_to_signed_magnitude(num: int, byteorder: Literal['big', 'little'] = 'big') -> bytes: | |
""" | |
encode a signed integer with the signed-magnitude format | |
""" | |
negative: bool = num < 0 | |
octets: bytearray = bytearray(unsigned_to_bytes(-num if negative else num, byteorder)) | |
significant: int = 0 if byteorder == 'big' else -1 # index of the most significant byte in octets | |
if octets[significant] & 0x80: | |
if byteorder == 'big': | |
octets[0:0] = b'\x00' # insert at the beginning | |
else: | |
octets += b'\x00' # insert at the end | |
if negative: | |
octets[significant] |= 0x80 | |
return octets | |
if __name__ == '__main__': | |
# big endian | |
assert int_to_signed_magnitude(-129) == bytes.fromhex('80 81') # 1000 0000 1000 0001 | |
assert int_to_signed_magnitude(-128) == bytes.fromhex('80 80') # 1000 0000 1000 0000 | |
assert int_to_signed_magnitude(-127) == bytes.fromhex('ff') # 1111 1111 | |
assert int_to_signed_magnitude(-1) == bytes.fromhex('81') # 1000 0001 | |
assert int_to_signed_magnitude(0) == bytes.fromhex('00') # 0000 0000 | |
assert int_to_signed_magnitude(1) == bytes.fromhex('01') # 0000 0001 | |
assert int_to_signed_magnitude(127) == bytes.fromhex('7f') # 0111 1111 | |
assert int_to_signed_magnitude(128) == bytes.fromhex('00 80') # 0000 0000 1000 0000 | |
assert int_to_signed_magnitude(129) == bytes.fromhex('00 81') # 0000 0000 1000 0001 | |
# little endian | |
assert int_to_signed_magnitude(-129, 'little') == bytes.fromhex('81 80') | |
assert int_to_signed_magnitude(-128, 'little') == bytes.fromhex('80 80') | |
assert int_to_signed_magnitude(-127, 'little') == bytes.fromhex('ff') | |
assert int_to_signed_magnitude(-1, 'little') == bytes.fromhex('81') | |
assert int_to_signed_magnitude(0, 'little') == bytes.fromhex('00') | |
assert int_to_signed_magnitude(1, 'little') == bytes.fromhex('01') | |
assert int_to_signed_magnitude(127, 'little') == bytes.fromhex('7f') | |
assert int_to_signed_magnitude(128, 'little') == bytes.fromhex('80 00') | |
assert int_to_signed_magnitude(129, 'little') == bytes.fromhex('81 00') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment