Can anyone explain me how &= assignment operator works in Python programming.
&= is a bitwise and operator. It works with the binary number. I'll explain this to you by an example
Example:
x = 5
In binary 5 is equal to 101
Now
x &= 3 which means x = x & 3
You also need to convert 3 to binary number which is 011
Now you need to apply and operator to both binary number
101
& 011
=001
So now convert this resulting binary number to decimal number which is equal to 1.
You can use online converter from decimal to binary and binary to decimal.
&= is a bitwise operator, it works with bits such as following,
a = 60 # 60 = 0011 1100
b = 13 # 13 = 0000 1101
c = 0
c = a & b; # 12 = 0000 1100
print ("c: ", c)
output:
c: 12
It works on the basis of logic given below
0&0= 0
0&1= 0
1&0= 0
1&1= 1
look at the comments i have given in the code.
Related
This question already has answers here:
Boolean operators vs Bitwise operators
(9 answers)
Closed 3 years ago.
This is a pretty trivial question that I haven't been able to find the answer to.
Here is the problem. I have the following array:
vals = [-5, 2]
And I want to check whether val[0] or val[1] is greater than 0. If either is true, then I should output True.
My immediate thought was to use; (vals[1] or vals[0]) > 0) but I'm finding that (5 | -2) > 0 is False where (5 or -2) > 0 is True
Any clarification would be much appreciated.
What is the difference between or and |?
or is a logical or and | is a bitwise or logical inclusive or.
The logical or
The logical or in python returns the first value that is true.
Example:
>>> None or False or 5
5
>>> -5 or 2
-5
The bitwise or logical inclusive or
The bitwise or logical inclusive or is represented by the | operator in python and creates a number where all bits are set that are set in at least one of the given numbers.
Example:
2 is in binary 0010
4 is in binary 0100
A logical or between the two results in 0110 which is 6.
>>> 2 | 4
6
How a negative number is stored is generally implementation specific. However on most systems a negative number is stored by creating the two's complement of the positive number by inverting each bit and adding 1.
That number in bitwise ore two any other number still results in a negative number:
>>> -5 | 2
-5
Neither of the two solves your problem
While using
(vals[1] or vals[0]) > 0
seems to work, it fails when you flip the values:
>>> vals = [2, -5]
>>> (vals[1] or vals[0]) > 0
False
You should check both values seperatly
>>> vals = [-5, 2]
>>> vals[0] > 0 or vals[1] > 0
True
For a larger input this may be inconvenient. You should use any with a generator expression:
>>> any(x > 0 for x in vals)
True
You want the any function:
>>> any(x > 0 for x in vals)
x | y computes the bitwise OR of the two values, while x or y evaluates to the first "truthy" value. In both cases, the result is then compared to 0: (x or y) > 0 and (x | y) > 0.
What you want to compare each value to zero (as necessary), with
vals[0] > 0 or vals[1] > 0
If you had three values, you'd write
vals[0] > 0 or vals[1] > 0 or vals[2] > 0
The any function generalizes this to a list of any size, without the need to decide how many terms to or together based on the size of the list.
To answer this question, I have to explain about Two's Complement.
BINARY REPRESENTATION OF NUMBERS
So you know how internally, an integer like 5 is represented as a binary string
00000000000000000000000000000101
How do you imagine you'd represent a negative number?
Well, here's what we want to do:
Addition should work the same with negative numbers and positive numbers; i.e. you do the same steps to add 4 + 9 as 4 + -9.
Integer overflow shouldn't break mathematics; i.e. MAX_VALUE + 1 == MIN_VALUE, MIN_VALUE - 1 == MAX_VALUE
So what we do is called "Two's Complement."
TWO'S COMPLEMENT
To represent a negative number, take its absolute value, bitflip every bit, and add 1.
So if the positive number is 5
00000000000000000000000000000101
the negative number -5 is
11111111111111111111111111111011
Essentially, this means we pick the number 01111111111111111111111111111111 to be the largest positive number, and all numbers after that are negative.
SO WHAT DOES (5 | -2) MEAN?
The | is the bitwise or operator. Given two numbers, it takes every bit and or's them together, constructing a new number where a digit is 1 if the digit in that position in wither or both of the two original numbers is 1, and 0 otherwise. The calculation looks like this:
5 -> 00000000000000000000000000000101
| -2 -> 11111111111111111111111111111110
---- --------------------------------
11111111111111111111111111111111 -> -1
So as you can see, 5 | -2 = -1 < 0.
WHAT ABOUT (5 or -2)?
The "or" operator takes two values, casts them to booleans and or's them together. This is important: it doesn't or the values, it returns the first value that is "truthy" -- in other words, if you put it in an if statement, it would run.
The only integer that isn't "truthy" is 0. Therefore (5 or -2) returns the first non-zero integer of 5 and 2, which is 5 > 0. So 5 or -2 = 5 > 0.
| is a bitwise OR, and Python uses two's complement representation for integers. Evaluating 5 | -2 gives:
... 0000 0000 0000 0101 (+5)
| ... 1111 1111 1111 1110 (-2)
──────────────────────────────
= ... 1111 1111 1111 1111 (-1)
And -1 is not greater than zero, so (5 | -2) > 0 is false.
or is a logical OR. Unlike in other languages where this operator returns a Boolean (True/False) value, Python defines x or y as being equivalent to x if x else y (except that x is evaluated only once). Note that any nonzero numeric value is “truthy” in Python, so if x≠0, then x or y evaluates to x.
>>> 5 or -2
5
>>> -2 or 5
-2
That (5 or -2) > 0 evaluates to True was a stroke of luck from having the positive number first. In the other order, you would have gotten False.
In general (x or y) > 0 is not equivalent to (x > 0) or (y > 0), which is what you meant.
When you do (5 | -2), you're doing a bitwise-OR. That will preserve the negation bit in the numbers. Therefore, you'll still have a negative number.
The (5 or -2) is a logical-OR, to the Python interpreter will extend that to the next logical operator (the greater-than).
They are two completely different operations so that is expected.
To illustrate, here's a small shell log:
In [1]: 5 or -2
Out[1]: 5
In [2]: 5 | -2
Out[2]: -1
The or operator returns the first non-zero (non-None, non-False, etc.) value.
The | operator does a bitwise or. To illustrate:
In [3]: bin(5)
Out[3]: '0b101'
In [4]: bin(-2)
Out[4]: '-0b10'
In [5]: bin(5 | -2)
Out[5]: '-0b1'
I am trying to output the binary representation of an negative number with the least bytes available each time.
Example:
-3 -> 101
-10 -> 10110
Here's a way to do this using the .bit_length method of Python 3 integers. It also uses the string .format method to do the integer to binary string conversion. This function returns a string starting with '0' for non-negative numbers so that they can be distinguished from negative numbers.
def twos_complement(n):
m = n + 1 if n < 0 else n
bitlen = 1 + m.bit_length()
mask = (1 << bitlen) - 1
return '{0:0{1}b}'.format(n & mask, bitlen)
for i in (-10, -3, 0, 3, 10):
print('{:3}: {}'.format(i, twos_complement(i)))
print('- ' * 30)
for i in range(-15, 16):
print(i, twos_complement(i))
output
-10: 10110
-3: 101
0: 0
3: 011
10: 01010
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-15 10001
-14 10010
-13 10011
-12 10100
-11 10101
-10 10110
-9 10111
-8 1000
-7 1001
-6 1010
-5 1011
-4 100
-3 101
-2 10
-1 1
0 0
1 01
2 010
3 011
4 0100
5 0101
6 0110
7 0111
8 01000
9 01001
10 01010
11 01011
12 01100
13 01101
14 01110
15 01111
How it works
Python uses a modified form of two's complement to represent integers. Python integers have no size limit, so negative integers behave as if they have an infinite number of leading 1 bits, as explained in the Python Wiki article on Bitwise Operators.
The int.bit_length method tells us the minimum number of bits required to represent a number, we want one more bit than that so that all our non-negative numbers will start with 0 and all the negative numbers start with a 1. We need to modify that slightly to ensure that numbers of the form -2**n will only get a single leading one bit, we do that by adding 1 to all the negative numbers when calculating the bit length.
To select the bits we want we need a bit mask of the appropriate length. If the bit length is 4, we want a mask of 1111 = 2**4 - 1; we _could calculate it by using exponentiation, but it's more efficient to use bit shifting: (1 << bitlen) - 1. We then do the bitwise AND operation n & mask to select the bits we want. Fortunately, Python gives us a non-negative number when we perform such masking operations. :)
Finally we convert the resulting integer to a string using the .format method. We use a nested format specification so we can dynamically specify the correct length of the output string. In
'{0:0{1}b}'.format(n & mask, bitlen)
the first 0 of the format spec says that we're converting the value of the 0 arg in the argument list (n & mask), the :0{1}b says to convert it to binary, padded with leading zeroes if necessary, using the value of the 1 arg in the argument list (bitlen) as the total string length.
You can read about nested format specs in the Format String Syntax section of the docs:
A format_spec field can also include nested replacement fields
within it. These nested replacement fields may contain a field name,
conversion flag and format specification, but deeper nesting is not
allowed. The replacement fields within the format_spec are
substituted before the format_spec string is interpreted. This
allows the formatting of a value to be dynamically specified.
I am looking for way to determine the number of characters my binary value takes up.
For example if my values binary values were 4, 20, and 60 I'd get the following results:
bin(4), 0b100 = 3
bin(20), 0b10100 = 5
bin(60), 0b111100 = 6
a = 20
a.bit_length()
>> 5
A positive integer n has b bits when 2b-1 ≤ n ≤ 2b – 1. So The number of bits required to represent an integer n is :
floor(log n)+1 # note that base of log is 2
And since you have 0b at the leading you need to add 2 to aforementioned formula.
So it would be :
floor(log n) + 3
And in python you can use math module like following:
math.floor(math.log(n, 2)) + 3
Example :
>>> math.floor(math.log(10, 2)) + 3
6.0
>>>
>>> len(bin(10))
6
>>> math.floor(math.log(77, 2)) + 3
9.0
>>> len(bin(77))
9
As a more Pythonic way you can also use int.bit_length which returns the number of bits needs to represent an integer object. So for get the number of require characters you can add it with 2 :
int.bit_length() + 2
I am trying to print the max number of bits (n) and also the max number those number of bits are able to represent. I feel as though the problem is in the x = x%2
input:
sortbit(3)
output:
000
111
000
111
000
111
000
111
expected output"
000
001
010
011
100
101
110
111
my code:
def sortbit(n):
max_num = 2**n
for x in range(0,max_num):
stringy = []
a = 0
while a < n:
a += 1
x = x % 2
if x == 0:
stringy.insert(a,'0')
else:
stringy.insert(a,'1')
t = ''.join(stringy)
print t
You are turning any number into either 1 or 0 with x = x % 2. You may as well just print str(x % 2) * n.
You need to use integer division instead, and test separately for even or odd.
Even better, you could just append the output of the modulus test, as string, to stringy:
stringy.insert(0, str(x % 2))
x = x // 2
Demo with the code simplified a bit:
>>> def sortbit(n):
... max_num = 2**n
... for x in range(max_num):
... stringy = []
... for a in range(n):
... stringy.append(str(x % 2))
... x //= 2
... print ''.join(reversed(stringy))
...
>>> sortbit(3)
000
001
010
011
100
101
110
111
You could also bitshift the value; the >> operator moves the bits to the right for you by a given number of steps; x >> 1 shifts the bits in x one step over, essentially dividing by two.
You could also look into the bin() function (returns the value as a binary string, starting with 0b), and the format() function, together with the str.format() method, which lets you format values as binary strings as well using the b output format. Printing your values in a loop could be as simple as:
def sortbit(n):
for i in range(2**n):
print '{:0{}b}'.format(i, n)
Last but not least, you are simply producing the product of the digits 0 and 1, n times. You could express that with itertools.product() as well:
>>> from itertools import product
>>> for bits in product('01', repeat=3):
... print ''.join(bits)
...
000
001
010
011
100
101
110
111
but that could be seen as cheating. :-)
You've got answers for your specific code, so here's a solution using Python's format to print n digits of binary with the appropriate number of leading zeroes:
>>> def sortbit(n):
... for i in range(2**n):
... print '{0:0{1}b}'.format(i,n)
...
>>> sortbit(2)
00
01
10
11
>>> sortbit(3)
000
001
010
011
100
101
110
111
You should use x % 2 in the if, not assigning back to x
if x % 2 == 0:
...
also at each iteration you should move over to next bit, otherwise you're adding the same bit over and over:
x = x >> 1
I've never used the >> and << operators, not because I've never needed them, but because I don't know if I could have used them, or where I should have.
100 >> 3 outputs 12 instead of 12.5. Why is this. Perhaps learning where to best use right shift will answer that implicitly, but I'm curious.
Right shift is not division
Let's look at what right-shift actually does, and it will become clear.
First, recall that a number is stored in memory as a collection of binary digits. If we have 8 bits of memory, we can store 2 as 00000010 and 5 as 00000101.
Right-shift takes those digits and shifts them to the right. For example, right-shifting our above two digits by one will give 00000001 and 00000010 respectively.
Notice that the lowest digit (right-most) is shifted off the end entirely and has no effect on the final result.
>> and << are the right and left bit shift operators, respectively. You should look at the binary representation of the numbers.
>>> bin(100)
'0b1100100'
>>> bin(12)
'0b1100'
The other answers explain the idea of bitshifting, but here's specifically what happens for 100>>3
100
128 64 32 16 8 4 2 1
0 1 1 0 0 1 0 0 = 100
100 >> 1
128 64 32 16 8 4 2 1
0 0 1 1 0 0 1 0 = 50
100 >> 2
128 64 32 16 8 4 2 1
0 0 0 1 1 0 0 1 = 25
100 >> 3
128 64 32 16 8 4 2 1
0 0 0 0 1 1 0 0 = 12
You won't often need to use it, unless you need some really quick division by 2, but even then, DON'T USE IT. it makes the code much more complicated then it needs to be, and the speed difference is unnoticeable.
The main time you'd ever need to use it would be if you're working with binary data, and you specifically need to shift the bits around. The only real use I've had for it was reading & writing ID3 tags, which stores size information in 7-bit bytes, like so:
0xxxxxxx 0xxxxxxx 0xxxxxxx 0xxxxxxx.
which would need to be put together like this:
0000xxxx xxxxxxxx xxxxxxxx xxxxxxxx
to give a normal integer in memory.
Bit shifting an integer gives another integer. For instance, the number 12 is written in binary as 0b1100. If we bit shift by 1 to the right, we get 0b110 = 6. If we bit shift by 2, we get 0b11 = 3. And lastly, if we bitshift by 3, we get 0b1 = 1 rather than 1.5. This is because the bits that are shifted beyond the register are lost.
One easy way to think of it is bitshifting to the right by N is the same as dividing by 2^N and then truncating the result.
I have read the answers above and just wanted to add a little bit more practical example, that I had seen before.
Let us assume, that you want to create a list of powers of two. So, you can do this using left shift:
n = 10
list_ = [1<<i for i in range(1, n+1)] # Where n is a maximum power.
print(list_)
# Output: [2, 4, 8, 16, 32, 64, 128, 256, 512, 1024]
You can timeit it if you want, but I am pretty sure, that the code above is one the fastest solutions for this problem. But what I cannot understand is when you can use right shift.