1

I'm working on audio codecs in Python (yikes) using byte arrays to edit individual byte data from an audio file.

I have a certain encryption in mind that requires me to perform bit wise operations on single bytes stored in the byte-array.

One of those operations is the ~ operator (bitwise NOT) which essentially reverses the bit (b'0001 becomes b'1110).

The problem is when you reference a single element of a byte array, it returns an int (does Python by default consider untyped 8 bit data integers?). Integers in Python are by default signed (I don't think unsigned integers even exist in Python).

When you try to perform bit-wise NOT on a byte in the byte-array, you get the following error:

>>> array[0] = ~array[0]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: byte must be in range(0, 256)

This is because it expects an unsigned int between 0-255. How do I convert a signed int into an unsigned int such that the bits used to represent both values remain the same?

Cheers

3
  • I think numpy should provide unsigned ints. I would try np.array(array).astype(np.uint8) Commented May 2, 2018 at 22:31
  • "I have a certain encryption in mind" - are you writing your own crypto? Please don't write your own crypto. Commented May 2, 2018 at 22:39
  • Hahah no... I wouldn't ever try that... trying to emulate something else Commented May 2, 2018 at 22:40

2 Answers 2

2

Use a different operation for bit flipping.

E.g.:1

array[i] = 255 - array[i]

or also:

array[i] = 255 ^ array[i]

will flip all (i.e.: 8) bits.


1 the math behind this can be worked out from two's complement wikipedia page.

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

6 Comments

Wouldn't it be 256 - array[0] ? Appreciate the quick response. Stuff like this makes me feel stupid hehe.
@JonathanMay: No. If array[0] is initially 0, then 256 - array[0] is 256, but the desired output is 255.
@JonathanMay: why don't you try it and see? for i in range(256): print('{:08b} {:08b}'.format(i, 255-i))
@JonathanMay: actually: all([{'0':'1','1':'0'}[c] for c in f'{i:08b}']==list('{:08b}'.format(255-i)) for i in range(256)) == True
@JonathanMay: ~0 gives -1, but this answer doesn't involve ~.
|
-1

The solution is actually remarkably simple after playing around with a binary calculator a little bit.

Just subtract the magnitude of the SIGNED int from 256, to get the value of the UNSIGNED int with the same binary representation.

So,

-23 signed would be 233 unsigned.

Hope this helps anyone else looking for a solution :)

EDIT: For those saying answer is 255 - array[0]. In this case I'm looking for a way to go from post NOT'd int to its unsigned counter part. So I've already performed the bitwise NOT on the integer, now I'm just getting it back to a form that can be inputted into the byte-array.

So in the end it would look something like this:

tmp = ~array[0]
array[0] = 256 + tmp

or

array[0] = 256 - abs(tmp)

This gets me the correct answer :)

3 Comments

Not 256. 255. Subtracting from 256 changes the range from 0-255 to 1-256.
Or if you're already working with the output of ~, then you need to add it to 256, not subtract.
If you take a number, say -12. In binary, that's 11110100. If you then convert 11110100 into an unsigned int, you get 244. Did I go wrong anywhere there?

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.