3

Let's say I have the

array = [1,2,3,4]

What I want is NOT to convert to the number 1234; but to take the bits of 1, 2, 3 and 4, concatenate them and convert back to a number.

In other words, I would have to perhaps convert each number/digit to binary, concatenate them and then convert back to a number.

Therefore, 1,2,3,4 would be 00000001, 00000010, 00000011, 00000100 respectively. Concatenating them would lead to 00000001000000100000001100000100 which converted to an unsigned int would be 16909060

Keep in mind that the digits from the array come from ord(characters), so they should be 8bits in length, therefore concatenated should lead to a 32bit number

How would I do that?

Dimebag
  • 833
  • 2
  • 9
  • 29

5 Answers5

4

In this simple case perhaps this suffices:

result = array[0] << 24 | array[1] << 16 | array[2] << 8 | array[3]

For example:

array = [1, 2, 3, 4]
result = array[0] << 24 | array[1] << 16 | array[2] << 8 | array[3]
print result

Prints this:

16909060
Elektito
  • 3,863
  • 8
  • 42
  • 72
  • 3
    No idea why this was downvoted. It seems completely correct. All the other answers are using complicated constructs, whereas this answer shows how simple it is. – wvdz Apr 25 '15 at 12:47
  • This is amazingly simple. May I ask if there's a way to do it in reverse? So given the 32bit integer, split it into 4 8bit integers? I'm thinking maybe `result >> 24` would give the first number? – Dimebag Apr 25 '15 at 14:45
  • To do it in reverse, you just need to use bitmasks: `result & 0xff000000` yields `array[0]`, `result & 0x00ff0000` yields `array[1]` and so on. – Elektito Apr 25 '15 at 15:00
1

The usual way to manipulate arrays of bytes in Python is with the struct module. Beware of the byte order, if necessary.

Python 3

>>> import struct
>>> i, = struct.unpack("<i", bytes([1, 2, 3, 4]))
>>> i
67305985
>>> 

Python 2 & 3

>>> import struct
>>> i, = struct.unpack("<i", struct.pack("4B", *[1, 2, 3, 4]))
>>> i
67305985
>>> 
Cilyan
  • 7,883
  • 1
  • 29
  • 37
  • 1
    Umm that construct exactly returns `struct.error: unpack requires a string argument of length 4`. Is your solution perhaps unique to Python 3? I'm using Python 2.7 – Dimebag Apr 25 '15 at 12:17
  • 1
    Yes, `bytes` in Python 3 refers to what was the `str` type in Python 2 (as Python 3 `str` is what was `unicode` in Python 2). For Python 2, use `struct.pack("4B", *array)` instead of `bytes(array)`. – chepner Apr 25 '15 at 12:37
  • 1
    Does not qualify as an answer. It's possible that this code is a good solution, but it is sufficiently obscure to warrant an explanation. – wvdz Apr 25 '15 at 12:49
  • 1
    This uses the host computer's byte order which might not be what the OP expects. – Elektito Apr 25 '15 at 12:52
  • Though that would be sufficient to put OP on the right track, but anyway. I improved the answer. Thanks for you comments :) – Cilyan Apr 25 '15 at 13:41
1
sum([v << i * 8 for i, v in enumerate(reversed(array))])
iced
  • 1,562
  • 8
  • 10
  • it actually is - there is nothing here which requires any explanation - enumerate/reversed can be looked up in python stdlib docs, list comprehension is explained in any python tutorial/book and, I believe, any python dev understand it. – iced Apr 25 '15 at 13:49
  • 3
    Nearly every question is answerable here by google, the main function of the site is to make this googling phase of the problem solving easier. – peterh Apr 25 '15 at 13:53
  • explanation is required for complex pieces of code. this one is as simple as it could be. – iced Apr 25 '15 at 14:00
  • @Veedrac I am sorry - I found this answer in the "low quality posts" queue, which is - as you can see - quite large. Most people doesn't even comment similar posts, only votes to close/delete it. I commented, trying to advice iced. Looks at least 3 people agreed with it. Maybe it wasn't enough polite, I am sorry for that, (also I am sorry, iced) my goal was to give an advice and not to hurt him. Next time I will comment your more polite version. – peterh Apr 26 '15 at 18:21
  • I really don't care about phrasing, no need to be sorry. though I still don't agree with you and them 3 others, though I do understand that you commented without trying to understand question/answer. – iced Apr 27 '15 at 06:06
  • @peterh Thanks for being so earnest about it. You might be interested in [AutoReviewComments](http://stackapps.com/questions/2116/autoreviewcomments-pro-forma-comments-for-se), which lets you save common comments for quick posting. It's saved me quite a bit of time :). – Veedrac Apr 27 '15 at 12:12
0
array = [1,2,3,4]
new = []
for number in array:
    bits = bin(number).split('b')[1]
    #transform your number into a binary number (like 0b001), transforms that binary into an array split at b, so [0, 001] and takes the second number of that.
    while len(bits) < 8:
        bits = '0' + bits
        #turns the newly created binary number into an 8 number one
    new.append(bits)
output = '0b'
for item in new:
    output += item
    #puts all the binary's together to form a new, 32 bit binary
output = int(output, 2)
#turns the binary string an integer

using strings for this might not be the cleanest method, but it works.

inecrafter
  • 57
  • 7
0

If you prefer one line

>>> int("".join([bin(x)[2:].zfill(8) for x in a]),2)
16909060

Or step by step

Step 1. convert numbers to binary strings, excape 0bs

>>> a  = [1,2,3,4]
>>> b = [bin(x)[2:] for x in a]
>>> b
['1', '10', '11', '100']

Step 2. fill elements with zeros (zfill)

>>> c = [i.zfill(8) for i in b]
>>> c
['00000001', '00000010', '00000011', '00000100']

Step 3. join elements to make a new string

>>> d = "".join(c)
>>> d
'00000001000000100000001100000100'

Step 4. convert to 10 base number

>>> int(d,2)
16909060
marmeladze
  • 6,468
  • 3
  • 24
  • 45
  • same inefficient as @Gord's answer. – iced Apr 25 '15 at 13:51
  • @iced i read your comment under gord's answer. for general approach you are right - if you are dealing with bits you should use bit methods. but in this case(for numbers under 256 (which both solutions are limited to this bound), there is no matter which one you use. both take same time to spit a result. and my code is just equivalent to saying "hey mate you can also use this", nothing more :) btw, i am a philosophy researcher, not a software engineer :) – marmeladze Apr 25 '15 at 14:20