I'm testing some of the functionality of bitwise functions in python. I want to see if I can concatenate hex "strings" as a converted integer and save as a new hex string after applying logical bitwise operations.
def hst(self):
ref = 0
href = ['1b','1bfa','001','0010']
for i in range(0,len(href)):
if i > 0:
ref = ref << len(href[i])*4
ref = ref ^ int(href[i],16)
else:
ref = int(href[i],16)
return hex(ref)
I expect 1b1bfa0010010 but I get fa0001010.
Any thoughts as to why and how I might fix this? As I said, I'm just trying to learn how this all works. I don't wish to use any libraries, just what is included without an import statement.
It's not doing the shifting. I see from the print(hex(ref)):
shift: 0x1b00
xor: 0xfa
shift: 0xfa0000
xor: 0xfa0001
shift: 0xfa0001000
xor: 0xfa0001010
shift is happening but not correctly xoring to the right place.
OMG Windows, you suck! I get the wrong answer in windows only. Linux it works. Why does Windows suck so much?! Thank you both for helping!
Related
I am trying to write a python driver for a lidar sensor that only has a package for robot OS.
I was able to get the communication working on a Raspberry Pi and I am getting the data that I need.
I never really worked with bytearrays before and even python is pretty new to me.
The received data looks like this (png), but you can take a look at the documentation (pdf) as well.
So if I'm not mistaken, I have to combine three bits into two like this:
[0x5D, 0xC7, 0xD0] => [0x5DC, 0x7D0]
I think the aforementioned robot OS library does this here, but my c++ is even worse than my python :)
After I have the correct data I want to sort it into a 2D array but that's not a problem.
Can you point me in the right direction, or just suggest how to search for a solution?
Thank you for your help
So here's one solution (maybe not the cleanest but it's bit-manipulation so...):
arr = [0x5D, 0xC7, 0xD0]
byte_0 = arr[0] << 4 | (arr[1] >> 4)
byte_1 = (arr[1] & 0xF) << 8 | arr[2]
I'll try to go over this step by step. The three bytes are, in binary representation:
0b0101_1101
0b1100_0111
0b1101_0000
The << operator is the shift-operator. It moves the bits to the left the specified amount. Applying this to the first byte yields:
0b0101_1101 << 4 = 0b0101_1101_0000, effectively appending four zero's at the end.
The >> operator is basically equivalent to the << operator, just shifting it the other way round. It discards bits when they would go below position 0:
0b1100_0111 >> 4 = 0b1100
Finally, the | operator is the logical 'or' operator. It performs a bit-wise or operation where each result bit is '1' if one or both of the initial bits is '1'. It is only '0' when both bits are '0'. We can make use of this to 'override' the contents of the lower four bits of our result so far. Note that I have omitted leading zero's for simplicity, but here are the numbers padded with zeroes
0b0101_1101_0000 | 0b0000_0000_1100 = 0b0101_1101_1100. And there you have your first number. Now note that this is not a byte, rather you now need 12 bits to represent the number.
The same is done with the second byte. The only thing new here is the logical and operator (&). This operator yields '1' only if both bits are '1'. We can use this to mask out a part of interest of the byte:
0b1100_0111 & 0x1111 = 0b0111
I am using python3.5, Let
M = '\x09\x00\x00\x00\x01\x89\x02\xdb\xd6\x01\x49\x63\x74'
Why is the left part of the following comparison not equal to the right part?
> M.encode() == b'\x09\x00\x00\x00\x01\x89\x02\xdb\xd6\x01\x49\x63\x74'
$ FALSE
the type of both is bytes. How can I reach from M to a variable that contains the right part of the above comparison?
not an encoding specialist, but whatever the encoding you'll be choosing, if it's not correct, it will interpret characters and the result won't be the same as the bytes object.
It will work with pure ascii, but with your values it doesn't.
One way would be to rebuild the bytes object from character codes that ord provides:
M = '\x09\x00\x00\x00\x01\x89\x02\xdb\xd6\x01\x49\x63\x74'
N = b'\x09\x00\x00\x00\x01\x89\x02\xdb\xd6\x01\x49\x63\x74'
M2 = bytes(map(ord,M))
print(N == M2)
yields True :)
I am using python 2.7. I need to truncate a binary number from a x-bits to 8 bits (byte)
i will write an example of what i would like to do to make it clear and also because stackexchange doesn't leave me write my question for some reason, example:
0b1010101010100101 -> 0b10100101
i tried this workaround: converting it to string and then cutting it as a sub-string, but i didn't manage to make it working
str_cs = str(bin(cs))
str_cs = str_cs[to_cut:]
but i am facing many problem to convert it back to a binary number...
how would you truncate it?
Simply use a bitwise & with a byte of all 1s:
cs = cs & 0b11111111
# or, if you're feeling daring:
cs &= 0b11111111
Solution of Phydeaux much better but I was doing :
>>> cs=0b1010101010100101
>>> cs=int(bin(cs)[-8:], 2)
>>> bin(cs)
'0b10100101'
Based on what you were trying with str
I am looking for a slick function that reverses the digits of the binary representation of a number.
If f were such a function I would have
int(reversed(s),2) == f(int(s,2)) whenever s is a string of zeros and ones starting with 1.
Right now I am using lambda x: int(''.join(reversed(bin(x)[2:])),2)
which is ok as far as conciseness is concerned, but it seems like a pretty roundabout way of doing this.
I was wondering if there was a nicer (perhaps faster) way with bitwise operators and what not.
How about
int('{0:b}'.format(n)[::-1], 2)
or
int(bin(n)[:1:-1], 2)
The second method seems to be the faster of the two, however both are much faster than your current method:
import timeit
print timeit.timeit("int('{0:b}'.format(n)[::-1], 2)", 'n = 123456')
print timeit.timeit("int(bin(n)[:1:-1], 2)", 'n = 123456')
print timeit.timeit("int(''.join(reversed(bin(n)[2:])),2)", 'n = 123456')
1.13251614571
0.710681915283
2.23476600647
You could do it with shift operators like this:
def revbits(x):
rev = 0
while x:
rev <<= 1
rev += x & 1
x >>= 1
return rev
It doesn't seem any faster than your method, though (in fact, slightly slower for me).
Here is my suggestion:
In [83]: int(''.join(bin(x)[:1:-1]), 2)
Out[83]: 9987
Same method, slightly simplified.
I would argue your current method is perfectly fine, but you can lose the list() call, as str.join() will accept any iterable:
def binary_reverse(num):
return int(''.join(reversed(bin(num)[2:])), 2)
It would also advise against using lambda for anything but the simplest of functions, where it will only be used once, and makes surrounding code clearer by being inlined.
The reason I feel this is fine as it describes what you want to do - take the binary representation of a number, reverse it, then get a number again. That makes this code very readable, and that should be a priority.
There is an entire half chapter of Hacker's Delight devoted to this issue (Section 7-1: Reversing Bits and Bytes) using binary operations, bit shifts, and other goodies. Seems like these are all possible in Python and it should be much quicker than the binary-to-string-and-reverse methods.
The book isn't available publicly but I found this blog post that discusses some of it. The method shown in the blog post follows the following quote from the book:
Bit reversal can be done quite efficiently by interchanging adjacent
single bits, then interchanging adjacent 2-bit fields, and so on, as
shown below. These five assignment statements can be executed in any
order.
http://blog.sacaluta.com/2011/02/hackers-delight-reversing-bits.html
>>> def bit_rev(n):
... return int(bin(n)[:1:-1], 2)
...
>>> bit_rev(2)
1
>>>bit_rev(10)
5
What if you wanted to reverse the binary value based on a specific amount of bits, i.e. 1 = 2b'00000001? In this case the reverse value would be 2b'10000000 or 128 (dec) respectively 0x80 (hex).
def binary_reverse(num, bit_length):
# Convert to binary and pad with 0s on the left
bin_val = bin(num)[2:].zfill(bit_length)
return int(''.join(reversed(bin_val)), 2)
# Or, alternatively:
# return int(bin_val[::-1], 2)
I'm trying to convert some binary output from a file to different types, and I keep seeing odd things.
For instance, I have:
value = '\x11'
If you do
bin(ord(value))
you get the output
'0b10001'
whereas I was hoping to get
'0b00010001'
I'm basically trying to read in a 32 byte header, turn it into 1's and 0's, so I can grab various bits that have different meanings.
Why not just use bitwise operators?
def is_bit_set(i, x):
"""Check if the i-th bit in x is set"""
return x & (1 << i) > 0
To get the desired output, try:
"0b{:08b}".format(ord(value))
If efficiency is your concern, it's recommended to use native binary representation instead of literal(string) binary representation, for bitwise operation is much more compact and efficient.
format(ord('\x11'), '08b') will get you 00010001, which should be close enough to what you want.