12

Given an number and an encoding length, how can I convert the number to its binary representation as a tensor?

Eg, given the number 6 and width 8, how can I obtain the tensor:

(0, 0, 0, 0, 0, 1, 1, 0)
1

4 Answers 4

21

def binary(x, bits):
    mask = 2**torch.arange(bits).to(x.device, x.dtype)
    return x.unsqueeze(-1).bitwise_and(mask).ne(0).byte()

If you wanna reverse the order of bits, use it with torch.arange(bits-1,-1,-1) instead.

Sign up to request clarification or add additional context in comments.

2 Comments

this is so elegant
Also, the endianness of the output appears to be little. 👍
10

Tiana's answer was a good one. BTW, to convert Tiana's 2-base result back to 10-base numbers, one can do like this:

import torch
import numpy as np


def dec2bin(x, bits):
    # mask = 2 ** torch.arange(bits).to(x.device, x.dtype)
    mask = 2 ** torch.arange(bits - 1, -1, -1).to(x.device, x.dtype)
    return x.unsqueeze(-1).bitwise_and(mask).ne(0).float()


def bin2dec(b, bits):
    mask = 2 ** torch.arange(bits - 1, -1, -1).to(b.device, b.dtype)
    return torch.sum(mask * b, -1)


if __name__ == '__main__':
    NUM_BITS = 7
    d = torch.randint(0, 16, (3, 6))
    b = dec2bin(d, NUM_BITS)
    # print(d)
    # print(b)
    # print(b.shape)
    # print("num of total bits: {}".format(np.prod(b.shape)))

    d_rec = bin2dec(b, NUM_BITS)

    # print(d_rec)
    print(abs(d - d_rec).max())  # should be 0.

4 Comments

Why .float() and not .byte() as per the referenced answer?
Yes, in general cases you can use .byte() here. I used .float() because I needed to pass the results to a third-party evaluating program, which required the bits in float format. Anyway, all the numbers were still either 0 or 1.
Good answer, but actually nothing to deal with decimal... Input tensor 'x' is already in binary, the function puts its bits into separate tensors rather than convert its base!
For large integers (64 bits), this gives "RuntimeError: Overflow when unpacking long". Can anyone suggest a solution?
0

If the input is unsigned bytes and the output width is 8 bits:

>>> binary = np.unpackbits(np.array([0xaa, 0xf0], dtype=np.uint8))
>>> print(torch.tensor(binary))
tensor([1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0], dtype=torch.uint8)

Note that unpackbits() only operates with np.uint8.

Comments

-1
def decimal_to_binary_tensor(value, width=0):
    string = format(value, '0{}b'.format(width))
    binary = [0 if c == '0' else 1 for c in string]
    return torch.tensor(binary, dtype=torch.uint8)

Examples:

>>> print(decimal_to_binary_tensor(6, width=8))
tensor([0, 0, 0, 0, 0, 1, 1, 0], dtype=torch.uint8)

>>> print(decimal_to_binary_tensor(6))
tensor([1, 1, 0], dtype=torch.uint8)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.