How to encode list of numbers as base64
Question:
I have a list containing negative numbers, and want to encode the list with base64. How can I do that?
I tried:
l = [-10, -48, 100, -20]
bytes(l)
But I get the error:
ValueError: bytes must be in range(0, 256)
I expect the same output as my Java code:
byte[] bytes = {-10, -48, 100, -20};
String result = Base64Utils.encodeToUrlSafeString(bytes);
System.out.println(result); // 9tBk7A==
Answers:
The error arises because Python expects unsigned 8-bit data, which can be obtained with the modulo %
operation:
unsigned == signed % 2 ** num_bits
import base64
def to_unsigned(x, num_bits=8):
uplim_uint = 2 ** num_bits
return x % uplim_uint
l = [-10, -48, 100, -20]
base64.b64encode(bytes(to_unsigned(x) for x in l))
# b'9tBk7A=='
This can also be hard-coded for performance:
l = [-10, -48, 100, -20]
base64.b64encode(bytes(x % 64 for x in l))
# b'9tBk7A=='
To convert this back you need loop through base64.b64decode()
and convert the unsigned data back to signed reverting the %
with a ternary conditional operator:
signed == unsigned if unsigned < 2 ** (num_bits - 1) else unsigned - 2 ** num_bits
def to_signed(x, num_bits=8):
half = 2 ** (num_bits - 1)
uplim_uint = 2 * half
return x if x < half else x - uplim_uint
[to_signed(x) for x in base64.b64decode(b'9tBk7A==')]
# [-10, -48, 100, -20]
or, hard-coding the function:
[(x if x < 128 else x - 256) for x in base64.b64decode(b'9tBk7A==')]
# [-10, -48, 100, -20]
I have a list containing negative numbers, and want to encode the list with base64. How can I do that?
I tried:
l = [-10, -48, 100, -20]
bytes(l)
But I get the error:
ValueError: bytes must be in range(0, 256)
I expect the same output as my Java code:
byte[] bytes = {-10, -48, 100, -20};
String result = Base64Utils.encodeToUrlSafeString(bytes);
System.out.println(result); // 9tBk7A==
The error arises because Python expects unsigned 8-bit data, which can be obtained with the modulo %
operation:
unsigned == signed % 2 ** num_bits
import base64
def to_unsigned(x, num_bits=8):
uplim_uint = 2 ** num_bits
return x % uplim_uint
l = [-10, -48, 100, -20]
base64.b64encode(bytes(to_unsigned(x) for x in l))
# b'9tBk7A=='
This can also be hard-coded for performance:
l = [-10, -48, 100, -20]
base64.b64encode(bytes(x % 64 for x in l))
# b'9tBk7A=='
To convert this back you need loop through base64.b64decode()
and convert the unsigned data back to signed reverting the %
with a ternary conditional operator:
signed == unsigned if unsigned < 2 ** (num_bits - 1) else unsigned - 2 ** num_bits
def to_signed(x, num_bits=8):
half = 2 ** (num_bits - 1)
uplim_uint = 2 * half
return x if x < half else x - uplim_uint
[to_signed(x) for x in base64.b64decode(b'9tBk7A==')]
# [-10, -48, 100, -20]
or, hard-coding the function:
[(x if x < 128 else x - 256) for x in base64.b64decode(b'9tBk7A==')]
# [-10, -48, 100, -20]