Does a bitwise "and" operation prepend zeros to the binary representation? - python

When I use bitwise and operator(&) with the number of 1 to find out if a number x is odd or even (x & 1), does the interpreter change the binary representation of 1 according to the binary representation of x? For example:
2 & 1 -> 10 & 01 -> then perform comparison bitwise
5 & 1 -> 101 & 001 -> then perform comparison bitwise
100 & 1 -> 1100100 & 0000001 -> then perform comparison bitwise
Does it append zeros to the binary representation of 1 to perform bitwise and operation?
Looking at the cpython implementation, it looks like that it compares the digits according to size of the right argument. So in this case the example above works actually:
2 & 1 -> 10 & 1 -> 0 & 1 -> then perform comparison bitwise
5 & 1 -> 101 & 1 -> 1 & 1 -> then perform comparison bitwise
100 & 1 -> 1100100 & 1 -> 0 & 1 -> then perform comparison bitwise
Is my understanding right? I'm confused because of this image from Geeks for Geeks.

Conceptually, adding zeros to the shorter number gives the same result as ignoring excess digits in the longer number. They both do the same thing. Padding, however, is inefficient, so in practice you wouldn't want to do it.
The reason is because anything ANDed with 0 is 0. If you pad the short number to match the longer one and then AND the extra bits they're all going to result in 0. It works, but since you know the padded bits will just result in extra zeros, it's more efficient to ignore them and only iterate over the length of the shorter number.
Python only processes the overlapping digits. First, it conditionally swaps a and b to ensure b is the smaller number:
/* Swap a and b if necessary to ensure size_a >= size_b. */
if (size_a < size_b) {
z = a; a = b; b = z;
size_z = size_a; size_a = size_b; size_b = size_z;
negz = nega; nega = negb; negb = negz;
}
Then it iterates over the smaller size_b:
/* Compute digits for overlap of a and b. */
switch(op) {
case '&':
for (i = 0; i < size_b; ++i)
z->ob_digit[i] = a->ob_digit[i] & b->ob_digit[i];
break;
So my understanding is right, the image is just for intuition?
Yep, correct. The image is for conceptual understanding. It doesn't reflect how it's actually implemented in code.

Related

Bitwise AND with 0xFFFFFFFF in Python

5 & 0xFFFFFFFF # 5
-5 & 0xFFFFFFFF # 4294967291
In Python, why bitwise AND a negative number with 0xFFFFFFFF will give a different result? Since 0 & 1 = 0 and 1 & 1 = 1, should bitwise AND a number with 0xFFFFFFFF (11111111111111111111111111111111) keep every digit what it was?
To give some more illustration, in python, to get the bit representation of -5 you apply two's complement rule, that is: start from 5, flipped bits, add 1
-5 -> 0000....0000000101 (5 in binary) -> 1111....1111111010 (flipped) -> 1111....1111111011 (+1)
When you & it with 0xFF you are doing this:
1111....1111111011
& 0000....0011111111
= 000000000011111111 = +255
I've used 0xFF but that does not matter since as #Tom Karzes mentioned,
Python integers have no fixed width, so negative numbers are treated
as having an infinite number of leading 1s.
and positive numbers have an infinite number of leadin 0s.

Given a list of numbers in which every number appear twice except one. Return that number

I was asked to find out the number from a list of numbers in Python that is present only once inside the list. As usual, I could easily solve it using the normal method that immediately comes out:
class Solution(object):
def singleNumber(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
for i in nums:
if(nums.count(i) == 1):
return i
return nums[0]
Trying to find out another better way, Internet suggested me to use Bitwise XOR operation and provided the following code which was way faster and more efficient. Below is the code:
class Solution(object):
def singleNumber(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
a = 0
for i in nums:
a^=i
print(a)
return a
The logic was if we do a XOR operation on 2 same bits(0,0 or 1,1) the answer will always be 0 and it will be 1 if the bits are different. Using this, it came out with such an approach.
My mind bogs down at trying to realize how is the normal concept of XOR operation coming to be useful here! I understand the logic they said about that same and different bits but by their code, every time I perform a XOR with the next bit a new number pops out so how can then we guarantee that only the number which occurs once will be evolved?
I feel clueless. It might not be a good approach to have posted a code snippet and then ask for an explanation but I feel the solution is extremely intriguing and am dying to learn how bitwise XOR helped out! Please help if anyone has an idea! Thanks in advance.
Note : In the list, all numbers occur twice except for one.
The general constraints for this XOR solution are a bit different:
You have a list where exactly one number occurs an odd number of times and all other numbers occur an even number of times and need to find the odd one.
XOR flips the bits if they are identical:
b1 XOR b1 > b0
b0 XOR b0 > b0
b1 XOR b0 > b1
b0 XOR b1 > b1
You have an arbitrary start value (the first number in your list), f.e.:
01010111011111101
If all other numbers occur an even number of times, you see each bit pattern at least twice.
The first time you have pairs of bits and
flip every 0,1 bit to 1
flip every 1,0 bit to 1
flip every 1,1 bit to 0
then you encounter the same number again (because number even times in it):
you have a 1 bit from last flipping and encounter a 1 bit again so you flip to 0
you have a 1 bit from last flipping and encounter a 0 bit again so you stay at 1
you have a 0 bit from last flipping and encounter a 1 bit again so you flip to 1
and you are now back at your original number because even times occuring numbers cancel out:
101010010
xor 101010010
-------------
000000000
and if you XOR any other number with 000000000 you get exactly that other number back.
The relevant properties of the XOR operation are:
It is associative, so (a ^ b) ^ c == a ^ (b ^ c)
It is commutative, so a ^ b == b ^ a
It has 0 as an identity element, so a ^ 0 == 0 ^ a == a
Every element is its own inverse, so a ^ a == 0
So consider what happens when your input list is like [3, 4, 5, 4, 3]. From the first two properties, we have that (((3 ^ 4) ^ 5) ^ 4) ^ 3 is the same as (3 ^ 3) ^ (4 ^ 4) ^ 5, from the fourth property this is the same as 0 ^ 0 ^ 5, and from the third property the result is 5. Effectively, every element which appears an even number of times cancels out with itself, leaving just the element which occurs once (or an odd number of times).
I think without knowing the properties of XOR operation, it is difficult to understand what that code does
This is the property of XOR operation
If the bits are the same, the result is 0. If the bits are different, the result is 1.
Below table will give a clear idea of the above XOR property.
+---+---+---------+
| a | b | a XOR b |
+---+---+---------+
| 0 | 0 | 0 |
| 0 | 1 | 1 |
| 1 | 0 | 1 |
| 1 | 1 | 0 |
+---+---+---------+
The Solution to your question is based on this concept.
An interesting property of XOR is that
when you XOR the same number by itself even number of times you get a Zero
when you XOR the same number by itself odd number of times you get the number itself
Take for example - Number 2 (2 in binary is - 0010)
Let us
Perform XOR of 2 (even no. times)
0010
0010
----
0000 <- XOR (Value is 0)
Perform XOR of 2 (odd number of times)
0010
0010
0010
----
0010 <- XOR (Value is 2)
Whatever numbers are occuring for even number of times will eventually result in a Zero and Zero XORed with the number occuring odd number of times will give you the same number (that occurs odd number of times)
And the reason why a is initialized to 0 is because - 0 XOR x will give x itself
Say x = 3
0 -> 0000
3 -> 0011
----
0011 <- XOR (Value is 3)
Edit - Based on OP's doubt
For the input arr = [1,2,2,4,1] you are asking why you are getting arbitrary values - 1,3,1,5,4
They are not arbitrary. They are the result of XOR operation between a and i.
Initial value of a = 0
First Iteration: i = 1(0001); a = 0 (0000)
i: 0000
a: 0001
----
0001 -> Decimal value is 1 stored in a
Second Iteration: i = 2(0010); a = 1 (0001)
i: 0010
a: 0001
----
0011 -> Decimal value is 3 stored in a
Third Iteration: i = 2(0010); a = 3 (0011)
i: 0010
a: 0011
----
0001 -> Decimal value is 1 stored in a
Fourth Iteration: i = 4(0100); a = 1 (0001)
i: 0100
a: 0001
----
0101 -> Decimal value is 5 stored in a
Fifth Iteration: i = 1(0001); a = 5 (0101)
i: 0001
a: 0101
----
0100 -> Decimal value is 4 stored in a

Finding the set of n-bit integers related to a given integer by single bit 'hopping'

Given an n-bit integer, I want to find the set of n-bit integers which are related to my original integer by the interchange of a single 1 by a single 0 where the interchanged 1 and 0 must be adjacent
So what I want is to find some function such that for example, if I gave it the binary 1011 (11 in base 10) it returns 0111 and 1101 (7 and 13 in base 10)
ie. so this would look like:
>>> bit_hop(11, n=4)
[7, 13]
It's important that this function knows how many bits the number is because my other constraint is that I need this to have periodic boundary conditions such that for example 0111 would return not only 1011 but also 1110, ie. the edges of the binary number should be adjacent.
Also, as said, only one swapping should be allowed per hop. This means that bit_hop(1010) should return [1100, 0011, 1001, 0110]
Does anyone have any ideas on how one might go about doing this? I know that this should involve some clever usage of the >>, << and ^ operations but I'm having trouble seeing the synthesis.
To do this directly in binary, you have to notice a couple of things about the algorithm. First it always deals with adjacent bits, except for looping around from the first bit to the last. Second those bits must be different, if they're the same swapping them wouldn't do anything.
This code walks a 2-bit mask around the value and tests to see if the bits are different, then uses exclusive-or to swap them.
def bit_hop(x, n):
for i in range(n-1):
mask = 3 << i
if x & mask != 0 and x & mask != mask:
yield x ^ mask
mask = (1 << (n-1)) | 1
if x & mask != 0 and x & mask != mask:
yield x ^ mask

Sum of Two Integers without using "+" operator in python

Need some help understanding python solutions of leetcode 371. "Sum of Two Integers". I found https://discuss.leetcode.com/topic/49900/python-solution/2 is the most voted python solution, but I am having problem understand it.
How to understand the usage of "% MASK" and why "MASK = 0x100000000"?
How to understand "~((a % MIN_INT) ^ MAX_INT)"?
When sum beyond MAX_INT, the functions yells negative value (for example getSum(2147483647,2) = -2147483647), isn't that incorrect?
class Solution(object):
def getSum(self, a, b):
"""
:type a: int
:type b: int
:rtype: int
"""
MAX_INT = 0x7FFFFFFF
MIN_INT = 0x80000000
MASK = 0x100000000
while b:
a, b = (a ^ b) % MASK, ((a & b) << 1) % MASK
return a if a <= MAX_INT else ~((a % MIN_INT) ^ MAX_INT)
Let's disregard the MASK, MAX_INT and MIN_INT for a second.
Why does this black magic bitwise stuff work?
The reason why the calculation works is because (a ^ b) is "summing" the bits of a and b. Recall that bitwise xor is 1 when the bits differ, and 0 when the bits are the same. For example (where D is decimal and B is binary), 20D == 10100B, and 9D = 1001B:
10100
1001
-----
11101
and 11101B == 29D.
But, if you have a case with a carry, it doesn't work so well. For example, consider adding (bitwise xor) 20D and 20D.
10100
10100
-----
00000
Oops. 20 + 20 certainly doesn't equal 0. Enter the (a & b) << 1 term. This term represents the "carry" for each position. On the next iteration of the while loop, we add in the carry from the previous loop. So, if we go with the example we had before, we get:
# First iteration (a is 20, b is 20)
10100 ^ 10100 == 00000 # makes a 0
(10100 & 10100) << 1 == 101000 # makes b 40
# Second iteration:
000000 ^ 101000 == 101000 # Makes a 40
(000000 & 101000) << 1 == 0000000 # Makes b 0
Now b is 0, we are done, so return a. This algorithm works in general, not just for the specific cases I've outlined. Proof of correctness is left to the reader as an exercise ;)
What do the masks do?
All the masks are doing is ensuring that the value is an integer, because your code even has comments stating that a, b, and the return type are of type int. Thus, since the maximum possible int (32 bits) is 2147483647. So, if you add 2 to this value, like you did in your example, the int overflows and you get a negative value. You have to force this in Python, because it doesn't respect this int boundary that other strongly typed languages like Java and C++ have defined. Consider the following:
def get_sum(a, b):
while b:
a, b = (a ^ b), (a & b) << 1
return a
This is the version of getSum without the masks.
print get_sum(2147483647, 2)
outputs
2147483649
while
print Solution().getSum(2147483647, 2)
outputs
-2147483647
due to the overflow.
The moral of the story is the implementation is correct if you define the int type to only represent 32 bits.
Here is solution works in every case
cases
- -
- +
+ -
+ +
solution
python default int size is not 32bit, it is very large number, so to prevent overflow and stop running into infinite loop, we use 32bit mask to limit int size to 32bit (0xffffffff)
a,b=-1,-1
mask=0xffffffff
while (b & mask):
carry=a & b
a=a^b
b=carray <<1
print( (a&Mask) if b>0 else a)
For me, Matt's solution stuck in inifinite loop with inputs Solution().getSum(-1, 1)
So here is another (much slower) approach based on math:
import math
def getSum(a: int, b: int) -> int:
return int(math.log2(2**a * 2**b))

What does & mean in python [duplicate]

This question already has answers here:
Bitwise operation and usage
(17 answers)
Closed 10 months ago.
I came across the following code
numdigits = len(cardNumber)
oddeven = numdigits & 1
what exactly is going on here? I'm not sure what the "&" is doing.
Answer
The & symbol is a bitwise AND operator. Used with 1, it basically masks the value to extract the lowest bit, or in other words will tell you if the value is even or odd.
More Info on Python's & operator
For more information, see: http://wiki.python.org/moin/BitwiseOperators
Why it Works to check Odd vs. Even
EDIT: Adding this section since this answer is getting some love
The reason why ANDing a value with 1 tells if the value is odd or even may not be obvious at first.
The binary representation of a number is essentially the sum of a series of YES or NO for each power of 2 moving leftward starting in the rightmost digit with 1, 2, 4, 8, ...
There is only one way to represent any number in this way. E.g. the number 13 (base 10) can be written in binary as "1101" (or hexadecimal as 0xD, but that's beside the point). See here:
1 1 0 1
x x x x
8 4 2 1
= = = =
8 + 4 + 0 + 1 = 13
Notice that aside from the rightmost binary digit, all other 1 digits will add an even number (i.e. a multiple of 2) to the sum. So the only way to get an odd final sum is to add that odd 1 from the rightmost digit. So if we're curious if a number is odd or even, we can look at its binary representation and ignore everything except for the rightmost digit.
To do this, we use the bitwise AND operator. The value 1 in binary is expressed as 1:
0 0 0 1
x x x x
8 4 2 1
= = = =
0 + 0 + 0 + 1 = 1
ANDing a value with 1 like this will result in 1 if the value's rightmost bit is set, and 0 if it is not.
And because 0 is generally considered "false" in most languages, and non-zero values considered "true", we can simply say as a shortcut:
if (value & 1): do_something_with_odd_value()...
& is also used for taking the intersection of two Python sets:
set1 = {0,1,2,3}
set2 = {2,3,4,5}
print(set1 & set2)
>>>set([2, 3])
More generally, Python allows operator overloading, meaning you can write classes that re-interpret what the & operator does. This is how libraries such as Pandas and Numpy hijack &.
It's a bitwise operation, in this case assigning zero to oddeven if cardNumber has an even number of elements (and one otherwise).
As an example: suppose len(cardNumber) == 235. Then numdigits == 235, which is 0b11101011 in binary. Now 1 is '0b00000001' in binary, and when you "AND" them, bitwise, you'll get:
11101011
&
00000001
----------
= 00000001
Similarly, if numdigits were 234, you would get:
11101010
&
00000001
----------
= 00000000
So, it's basically a obfuscated way of checking if len(cardNumber) % 2. Probably written by someone with a C background, because it is not very pythonic - readability counts!
& is a bitwise and, which is an efficient way to do bit-level calculations. It is taking numdigits and and-ing it with 1, bit-by-bit.
It's a binary bitwise AND operator.

Categories

Resources