Is it possible to transform an integer into half a byte using the `to_bytes()` method

Let's say I have a series of integers:

var = [1, 5, 4, 17, 231, 89]

If I wanted to transform these into bytes, I could use the following code:

[(i).to_bytes(1, byteorder='big') for i in var]

Since each number in var is under 256, it can be represented using one byte per integer. However, if I had another list like this:

var = [1, 2, 15, 12]

This time, each integer can fit into half a byte, or more precisely, two integers can be packed into a single byte.

How would I specify that I want to combine two integers into a byte whenever feasible, both during conversion and back?

An example implementation could look like this:

var1 = [1, 5, 4, 17, 231, 89]
var2 = [1, 2, 15, 12]

def foo(var):
  if max(var) < 2**4:
    num_bytes = 0.5
  elif max(var) < 2**8:
    num_bytes = 1
  elif max(var) < 2**16:
    num_bytes = 2

  if num_bytes >= 1:
    return [(i).to_bytes(num_bytes, byteorder='big') for i in var], num_bytes
  elif num_bytes = 0.5:
    # convert var to list of nybbles
    # merge two nybbles into a byte
    # generate list of bytes (half the length of var)
    # return the result along with num_bytes

def unfoo(var, num_bytes):
  if num_bytes >= 1:
    print([int.from_bytes(i, 'big') for i in var])
  elif num_bytes = 0.5:
    # reprint original integer list here

I aim to change a list of integers into a list of bytes, arranging two nybbles within a byte when feasible, and then convert them back.

The desired outcome should be as follows:

a, b = foo(var1)
unfoo(a, b) # prints [1, 5, 4, 17, 231, 89]

a, b = foo(var2)
unfoo(a, b) # prints [1, 2, 15, 12]

I am not seeking the smallest representation possible for individual numbers. Take note of the max(list): if all values can be 8-bit, convert to 8-bit; if they are all able to fit in 16-bits, adjust accordingly; if each value fits in a nybble, pack two nybbles into a list of bytes.

In essence, how do you merge two single-nybble integers into a single byte? If I know that bytes must be divided into two parts, what approach should be taken? It is safe to assume that the initial list will be even.

Answer №1

To find out how many numbers can be stored in a byte, determine the maximum number that can fit and then shift each number by the appropriate amount to create a new list with combined numbers. For example, if two numbers can fit in a byte, the formula would be

new_number = (old_num1 << 4) + old_num2

def foo(var):
    num_bytes = math.ceil(1 + max(math.log2(x) for x in var)) / 8
    if num_bytes >= 1:
        num_bytes = int(num_bytes)
        return [(i).to_bytes(num_bytes, byteorder='big') for i in var], num_bytes
    elif num_bytes == 0.5:
        shift_bits = 4 
        new_list = [(a << shift_bits) + b for a, b in zip(var[::2], var[1::2])]
        return [(i).to_bytes(1, byteorder='big') for i in new_list], num_bytes

To reverse the operation performed by the function foo when num_bytes < 1, you need to unshift the bits by finding the number of bits shifted during the initial operation. By following the same logic as the previous explanation and using given variables like new_number, you can obtain old_num2 as the least-significant four bits (new_number & mask) and old_num1 as the most-significant four bits (new_number >> shift_bits)

def unfoo(var, num_bytes):
    if num_bytes >= 1:
        return [int.from_bytes(i, 'big') for i in var]
    elif num_bytes == 0.5:
        new_list = [int.from_bytes(i, 'big') for i in var]
        ret = []
        shift_bits = 4
        mask = int(2**shift_bits - 1)
        for i in new_list:
            b = i & mask
            a = (i >> shift_bits) & mask
            ret.append(a)
            ret.append(b)
        return ret

Testing this functionality:

var1 = [1, 5, 4, 17, 231, 89]
var2 = [1, 2, 15, 12]
        
a, b = foo(var1)
c = unfoo(a, b) # prints [1, 5, 4, 17, 231, 89]

print(var1)
print(c)


a2, b2 = foo(var2)
c2 = unfoo(a2, b2) # prints [1, 2, 15, 12]
print(var2)
print(c2)

The output confirms the expected results:

[1, 5, 4, 17, 231, 89]
[1, 5, 4, 17, 231, 89]
[1, 2, 15, 12]
[1, 2, 15, 12]

Answer №2

I created a pair of straightforward functions that allow you to combine two numbers into a single byte (assuming the numbers are small enough to fit within half a byte), and then separate them back out:

def packToByte(number1, number2):
    nybbleLimit = 2**4
    if number1 >= nybbleLimit or number2 >= nybbleLimit:
        raise ValueError("Input values must be within nybble size")
    return (number1 << 0x4 | number2).to_bytes(1, 'big')
    
def unpackByte(byte):
    byteToInt = int.from_bytes(byte, 'big')
    part1 = (byteToInt & 0xF0) >> 0x4
    part2 = (byteToInt & 0x0F)
    return part1, part2

You can apply these functions in the following manner:

inputNum1 = 5 # hexadecimal: 0x05
inputNum2 = 12 # hexadecimal: 0x0c

packedByte = packToByte(inputNum1, inputNum2)
print(hex(int.from_bytes(packedByte, 'big'))) # 0x5c

outputNum1, outputNum2 = unpackByte(packedByte)
print(outputNum1, outputNum2) # 5 12

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Issue with recording the outcomes, retrieving and recording data in Excel

I created this script to analyze a file containing 50,000 words but I'm struggling with the output. Currently, it is only displaying the last word in the file! Here is the code snippet: filename = 'words.txt' try: with open('G:& ...

Looking for clarification on how to address the following code issue?

for j in range(k_value): print(“Group %d”, % j), for ind in cluster_order[j, :10]: print(‘ %s’ % words[ind]) An error was encountered as shown below for j in range(k_value): print(“Group %d”, % j), for ind in cluster_order[j, :10]: prin ...

Why is my StableBaselines3 PPO model performing rollouts but not learning?

During the learning process of a model, there are two main phases: A rollout phase A learning phase Although my models go through the rollout phase, they never seem to enter the learning phase. This is evident in the text output in a Jupyter Notebook wit ...

Converting Python data structures to JSON format and then back to YAML

As someone new to Python, I am currently working on a simple program that can parse YAML to JSON and vice versa. Issue arises when using yaml2json as it converts YAML to JSON in a single line format. Despite this, a JSON validator confirms its correctness ...

Executing Python Selenium Tests in Headless Mode

I'm facing some challenges when trying to run Webdriver on a specific hub in headless mode using Pyvirtualdisplay. The generic code below works without any issues: class TestHub4444TestClass01(unittest.TestCase): def setUp(self): self.di ...

When trying to retrieve an element, Selenium may throw an exception indicating that there is an

Recently, I've been working on coding a bot that can automatically log in to a website. Right now, I've started with the code for the login process focusing only on collecting the email input field. try: WebDriverWait(bot, delay).unti ...

Find out which if condition was activated? (Python version 2.7)

How can I identify which if statement was executed? For example: string = "hello" if len(string) > 10: print("over 10") elif string == "hello": print("String is equal to hello") else: pass I am trying to make it more "pythonic" and have ...

Converting a Dataframe or CSV to a JSON object array

Calling all python experts, I have a simple query that needs addressing. Take a look at the data below: 0 <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="ed959691ab9f92d1dcc0c2">[email protected]</a> 1323916902 ...

Organizing webpage data into a dictionary stored in a table

I am currently working on extracting tables from a webpage in order to store the headers as keys and the body as values, while also denoting which page they belong to. Here's my attempted code snippet: from selenium import webdriver from selenium.webd ...

What is the best way to create an executable file from a Python package using pyinstaller?

I have developed a Python command line program that is open source and compatible with Python 2.7, Python3+, and works across different platforms. My goal now is to package this program into an executable for my Windows users in a more user-friendly way. ...

Python implementation of the Velocity-Verlet algorithm for a double-well potential

Currently, I am working on implementing the Verlet algorithm to model a double well potential V(x) = x^4-20x^2 in order to create a basic phase portrait. However, the resulting phase portrait has an irregular oval shape and appears to be incorrect. I suspe ...

The Python code encountered a "stale element reference" error, indicating that the element is no longer connected to the

My current project involves scraping Amazon products, specifically focusing on clicking through various categories. However, I am encountering an issue where the code only works for the first category in the loop and throws an error. Despite researching so ...

Difficulty in locating tests with coverage detection

The coverage tool doesn't seem to be capturing the test coverage for the tests located in the directory tests. The actual source files are stored in another directory named src. (For privacy reasons, file names have been altered.) Shown below is the ...

How can I exclude specific lines from an XML file using filters?

Let's say I have the following data: <div class="info"><p><b>Orange</b>, <b>One</b>, ... <div class="info"><p><b>Blue</b>, <b>Two</b>, ... <div class="info"><p><b& ...

Generate a list of JSON strings using a collection of Pydantic objects

I have been working on extracting a list of JSON strings from a collection of Pydantic objects. My current approach involves the following code snippet: raw_books = [json.dumps(x.dict()) for x in batch.books] While this method functions properly, it tends ...

implement a search feature within a linked list structure

My goal is to implement a search function in Python for linked lists. The purpose of this function is to search for a specific string within the linked list nodes (where each node contains a word). For example, given a linked list with nodes: I -> am ...

Unusual behavior of send_keys function in Selenium using Python

When using Selenium with PhantomJS (python 2.7), I encountered an issue while trying to input text into a text box on a page (Cisco Unity 7). Upon inspection, it seemed that only 2 keys were being sent instead of the full password "12345678". This was part ...

Generator causes Two-Sum to Run Out of Time

Currently, I am working on solving various problems and have been exploring different approaches for the two-sum problem. Initially, I came up with the following solution: nums = [2,7,11,15] target = 9 def twoSum(nums: List[int], target: int) -> List[ ...

Using Python Selenium, I am attempting to upload an image to Instagram

Once I've dealt with the notification, my goal is to click on the create button, select an image, and then click the next button. Can someone assist me in uploading photos to Instagram? Here's my code: `def upload_images(username, password, imag ...

Intersecting Rectangles in Pygame

Currently, I'm working on creating a basic game using pygame, but I've encountered an issue that I need assistance with. Let's say we have two sprites, named sprite1 and sprite2, each with their own rect and image. These sprites are interac ...