Alen K.
Alen K.

Reputation: 65

How to convert bytearray in python 2.7 to decimal string?

I have the following byte array

>>> string_ba
bytearray(b'4\x00/\t\xb5')

which is easily converted to hex string with the next 2 lines:

hex_string = [chr(x).encode('hex') for x in string_ba]
hex_string = ''.join(hex_string)

that return

>>> hex_string.lower()
'34002f09b5'

which is expected. (This is an RFID card signature)

I convert this to decimal by doing the above and then converting from hex string to decimal string (padded with zeroes) with the next line. I have a limit of 10 characters in string, so I'm forced to remove the first 2 characters in the string to be able to convert it to, at most, 10 character decimal number.

dec_string = str(int(hex_string[2:], 16)).zfill(10)
>>> dec_string
'0003082677'

which is correct, as I tested this with an online converter (hex: 002f09b5, dec: 3082677) The question is, if there's a way to skip converting from bytearray to hex_string, to obtain a decimal string. In other words to go straight from bytearray to dec_string

This will be running on Python 2.7.15.

>>> sys.version
'2.7.15rc1 (default, Apr 15 2018, 21:51:34) \n[GCC 7.3.0]'

I've tried removing the first element from bytearray and then converting it to string directly and joining. But this does not provide the desired result.

string_ba = string_ba[1:]
test_string = [str(x) for x in string_ba]
test_dec_string = ''.join(test_string).zfill(10)

>>> test_dec_string
'0000479181'

To repeat the question is there a way to go straight from bytearray to decimal string

Upvotes: 2

Views: 2467

Answers (2)

CristiFati
CristiFati

Reputation: 41112

A number (let's call it X) consisting of n digits (in a base, let's refer to it as B) is written as:

Dn-1Dn-2Dn-3...D2D1D0 (where each Di is a digit in base B)

and its value can be computed based on the formula:

VX = Σin=-01(Bi * Di) (notice that in this example the number is traversed from right to left - the traversing sense doesn't affect the final value).

As an example, number 2468 (B10) = 100 * 8 + 101 * 6 + 102 * 4 + 103 * 2 (= 8 + 60 + 400 + 2000).

An ASCII string is actually a number in base 256 (0x100), where each char (byte) is a digit.

Here's an alternative based on the above:

  • It only performs mathematical operations on integers (the conversion to string is done only at the end)
  • The traversing sense (from above) is helpful with the restriction (final (decimal) number must fit in a number of digits, and in case of overflow the most significant ones are to be ignored)
  • The algorithm is simple, starting from the right, compute the partial number value, until reaching the maximum allowed value, or exhausting the number digits (string chars)

code.py:

#!/usr/bin/env python

import sys 


DEFAULT_MAX_DIGITS = 10


def convert(array, max_digits=DEFAULT_MAX_DIGITS):
    max_val = 10 ** max_digits
    number_val = 0
    for idx, digit in enumerate(reversed(array)):
        cur_val = 256 ** idx * digit
        if number_val + cur_val > max_val:
            break
        number_val += cur_val
    return str(number_val).zfill(max_digits)


def main():
    b = bytearray("4\x00/\t\xb5")
    print("b: {:}\n".format(repr(b)))
    for max_digits in range(6, 15, 2):
        print("Conversion of b (with max {:02d} digits): {:}{:s}".format(
            max_digits, convert(b, max_digits=max_digits),
            " (!!! Default case - required in the question)" if max_digits == DEFAULT_MAX_DIGITS else ""
        ))


if __name__ == "__main__":
    print("Python {:s} on {:s}\n".format(sys.version, sys.platform))
    main() 

Outpput:

(py_064_02.07.15_test0) e:\Work\Dev\StackOverflow\q054091895>"e:\Work\Dev\VEnvs\py_064_02.07.15_test0\Scripts\python.exe" code.py
Python 2.7.15 (v2.7.15:ca079a3ea3, Apr 30 2018, 16:30:26) [MSC v.1500 64 bit (AMD64)] on win32

b: bytearray(b'4\x00/\t\xb5')

Conversion of b (with max 06 digits): 002485
Conversion of b (with max 08 digits): 03082677
Conversion of b (with max 10 digits): 0003082677 (!!! Default case - required in the question)
Conversion of b (with max 12 digits): 223341382069
Conversion of b (with max 14 digits): 00223341382069

Upvotes: 1

Hamid Askarov
Hamid Askarov

Reputation: 28

You can use struct library to convert bytearray to decimal. https://codereview.stackexchange.com/questions/142915/converting-a-bytearray-into-an-integer maybe help you

Upvotes: 1

Related Questions