Python XOR of all the bits of an integer - python

I would like to know if an integer's binary representation has an odd number of bits equal to one.
There is a trivial solution by manipulating bytes and using a few shifts but I think that it is more costly than using a XOR of every bits.
Is there a way to manipulate bits directly instead of bytes ?

int type is unbounded in python so this could be one way:
number = 34
i = 0
for n in bin(number):
if n == '1':
i += 1
if i % 2 == 0:
print('even')
else:
print('odd')
I wanted to try an alternative for not having to use strings.
number = 4
mask = 1 << (int.bit_length(number) - 1) if number > 0 else 0
ones = 0
while mask > 0:
if number & mask > 0:
ones += 1
mask >>= 1
if bool(ones % 2):
print('odd')
else:
print('even')
Just a comment: I had to handle the exception in case the number has the value 0 because, in this case, the 'bit_length' method of the 'int' class returns 0.
mask = 1 << (int.bit_length(number) - 1) if number > 0 else 0
I disagree because at least one bit is needed to represent the value 0 . After that it can be turned on or off but at least one is required. For example the 'bin' function with parameter 0 returns '0b0' and not '0b' or ''.
>>> bin(0)
'0b0'
I think int.bit_length(0) should return 1. Pyton tooltip tells: "Number of bits necessary to represent self in binary".

Related

How to replace the independent 1 with 0 in binary number using only bitwise operations?

By "independent 1" I mean 1 that has no other 1 next to it ("010" or "10" and "01" at the ends of the num.)
If the 1 doesn´t have any 1 next to it, it will change to 0.
For example:
11010 = 11000
10101 = 00000
1111 = 1111
I can´t use for or while loops. Only bitwise operators.
I tried something like this:
num = 0b11010
count = 0
if num & 1 == 1:
if (num >> 1) & 1 == 1 or (num << 1) & 1 == 1:
count += 1
else:
count += 0
if (num >> 1) & 1 == 1:
if (num >> 2) & 1 == 1 or (num >> 0) & 1 == 1:
count += 2
else:
count += 0
.
.
.
#(Same principle)
But the code will get too long when I try to implement it for bigger numbers.
This is a good exercise in bit shifting and bit comparison. One way this can be solved (there's probably several different ways) is by storing a left shifted and right shifted version of the original number. From there, you can use the XOR function to detect which bits are different. If both neighbors of a 1 are 0, then the XORs (as shown below) will simultaneously be 1. At that point, we have the 1's which are neighbored by two zeros. Then we can invert the value to highlight all the bits except for the bits we just found. Comparing that number with the original number with the AND function will 'erase' the bits from the original number.
It's not so easy to explain this without visuals, so hopefully a look at the code will help in understanding. I'm assuming a 32-bit length here.
num = 0b11010
# Assume 32 bit, make sure only zeros are shifted in on either side
num_l1 = (num<<1)&(~0x1) # make sure the new right bit is zero
num_r1 = (num>>1)&(~0x80000000) # make sure the new left bit is zero
# Print the left and right shifted numbers along with num. As we can see, we
# are looking for bits which are a 1 in the num, but a 0 in both left and right
# shift.
print(f' Left Shifted Number: {"{:032b}".format((num<<1)&(~0x1))}')
print(f' Number: {"{:032b}".format(num)}')
print(f'Right Shifted Number: {"{:032b}".format((num>>1)&(~0x80000000))}')
# XORing with left and right will highlight values that are either 010 or 101 in
# the original num. We only want 010, so we then AND the new sequence with
# the original num to only allow 010 sequences to pass.
find_lonely_ones = num & ((num^num_l1) & (num^num_r1))
# We can then invert the lonely bits and AND with the original num
new_num = num & (~find_lonely_ones)
print()
print(f' Number: {"{:0b}".format(num)}')
print(f'Final Answer: {"{:0b}".format(new_num)}')
# We can print each step for clarification
print()
print(f' Left Shifted Number XOR Number: {"{:032b}".format(num^num_l1)}')
print(f'Right Shifted Number XOR Number: {"{:032b}".format(num^num_r1)}')
print(f' AND of the above operations: {"{:032b}".format((num^num_l1) & (num^num_r1))}')
print(f' The above value AND Number: {"{:032b}".format(find_lonely_ones)}')
print(f' NOT the above value AND Number: {"{:032b}".format(num & (~find_lonely_ones))}')
Maybe this code can give you some idea:
a = [3, 5, 8, 1, 2, 7]
b = [2, 6, 8]
lenA, lenB = len(a), len(b)
# Getting the absolute value of abs
diff = abs(lenA - lenB)
if lenA < lenB:
# extend expands the list. will add an absolute value of zero to the end
a.extend([0]*diff)
else:
b.extend([0]*diff)
print(b)

Efficient code to count the number of trailing 0s at the end of a binary number

I was looking into a method for finding the number of trailing zeros in binary numbers and came across a solution in C (link). I am looking for a solution in Python!
Binary Input -> 1000
Output: 3
Binary Input -> 101101001100
Output: 2
Binary Input -> 1010001010000
Output: 4
Binary Input -> 100000001
Output: 0
Is there an efficient way of doing this without iterating the binary number as a string or using string methods for filtering? Basically, I may have a very large number of very very large binary numbers, so I am trying to find something more efficient than simply iterating over it as a string.
EDIT:
Here is my attempt -
def trailingzeros(l):
count = 0
a = [i for i in str(l)]
for i in reversed(a):
if i=='0':
count+=1
else:
break
return count
NOTE: I am looking for a solution that exploits the binary nature of the input.
n = 0b1010001010000
count = 0
while n:
if (n&1):
break
n >>= 1
count += 1
print(count)
Prints:
4
You can use python bit operators:
def findTrailing0(num):
count = 0
lastBit = 0
while num != 0:
lastBit = num & 0x1
if lastBit != 0:
break
count += 1
num >>= 1
return count

Reversing an integer using recursion in Python

While practicing recursion I came across a question to reverse an integer using recursion. I tried to do the question without converting the integer into a string.
I was able to solve the question partially but the output would always come without any of the zeroes from the original input. Below is the code I came up with:
def reverseNumber(n):
if (n//10) == 0:
return n
lastDigit = n%10
ans = reverseNumber(n//10)
nod = 0
for i in str(ans):
nod += 1
return (10**nod)*lastDigit + ans
Upon inspection I could see that this was happening because when lastDigit is 0 it only returned the reversed integer from the recursive call i.e input 4230 will give 324.
But this also meant that all zeroes between the original input would also get removed as we went deeper in the recursive calls.
So please tell me how to modify this code so that zeroes in the original input are not removed while reversing.
You probably need just this:
def rev(n):
if n>0:
return str(n%10)+rev(n//10)
else:
return ''
reverseNumber should return an int and accept positive and negative numbers.
The simplest way to fix your code, without handling negative numbers, is:
def reverseNumber(n):
if n == 0:
return 0
lastDigit = n%10
n //= 10
return int(str(lastDigit) + str(reverseNumber(n))) if n else lastDigit
for test in (0, 123, 120):
print(test, reverseNumber(test))
Prints:
0 0
123 321
120 21
Yes! The reverse of 120 is 21 when you are dealing with int types as opposed to str types.
Another implementation that does handle negative numbers takes a whole different approach:
I have broken this out into two functions. Function rev is a generator function that assumes that it is being called with a positive, non-negative number and will recursively yield successive digits of the number in reverse. reverseNumber will join these numbers, convert to an int, adjust the sign and return the final result.
def reverseNumber(n):
def rev(n):
assert n >= 0
yield str(n % 10)
n //= 10
if n != 0:
yield from rev(n)
if n == 0: return 0 # special case
x = int(''.join(rev(abs(n))))
return x if n >= 0 else -x
tests = [0, 132, -132, 120]
for test in tests:
print(test, reverseNumber(test))
Prints:
0 0
132 231
-132 -231
120 21
For all non-negative n, when n < 10 it is a single digit and already the same as its reverse -
def reverse(n = 0):
if n < 10:
return str(n)
else
return str(n%10) + rev(n//10)
you can also try the following Python3 code. It will cover positive and negative integers to be reversed as integers - not as strings ...
x = int(input("What integer shall be reversed? "))
n = abs(x) # ... to handle negative integers
r = 0 # ... will hold the reversed int.
while n > 0: # Recursion part reversing int.
r = (r * 10) + (n % 10) # using '%' modulo
n = int(n / 10) # and a 'dirty way' to floor
if x < 0: # Turn result neg. if x was neg.
return (r * -1)
else:
return r # Keep result pos. if x was pos.
This approach will leave your zeros in the middle of the integer intact, though it will make any zero at the end of the initial number vanish - rightfully so as integers do not start with a zero. ;))

how many '1' in a 32-bits integer programmed with python

I have succeeded ran the code in C++,with the code below:
int countOnes(int num) {
int count =0;
while (num) {
count ++;
num = num & (num-1);
}
return count;
}
but it didn't work in Python version:
def countOnes(num):
count = 0
while(num):
count += 1
num = num&(num-1)
return count
It seems blocked when the num = -1(0Xffffffff), why does it work in C++, but not in python?
The reason this function works differently in the two languages is that they have different fundamental number types. In C++, int is indeed often a 32 bit integer in two's complement representation, though the language standard allows other representations. In Python, however, the standard number type has arbitrary precision.
The continuation criterion for your loop is that num is non-zero. If it doesn't terminate, let's add some debugging to see what happens instead:
def countOnes(num):
count = 0
while(num):
count += 1
num = num&(num-1)
print(num) # <-- inspect what happens to num
return count
Let's see what we get for different inputs:
>>> countOnes(1)
0
1
>>> countOnes(7)
6
4
0
3
For -1, however, things quickly go out of hand:
>>> countOnes(-1)
-2
-4
-8
-16
-32
-64
-128
-256
-512
-1024
-2048
-4096
...
num keeps decreasing. Since the number type has arbitrary size, the number will only keep growing more negative.
To simulate the fixed precision of the C integer, you can limit num to 32 bits:
def countOnes(num):
num = num & 0xffffffff # <-- Limit num to 32 bits
count = 0
while(num):
count += 1
num = num&(num-1)
return count
With debugging output, the output for countOnes(-1) is now:
>>> countOnes(-1)
4294967294
4294967292
4294967288
4294967280
4294967264
4294967232
4294967168
4294967040
4294966784
4294966272
4294965248
4294963200
4294959104
4294950912
4294934528
4294901760
4294836224
4294705152
4294443008
4293918720
4292870144
4290772992
4286578688
4278190080
4261412864
4227858432
4160749568
4026531840
3758096384
3221225472
2147483648
0
32
as desired :)
Python doesn't have "32-bit integers". Its integers are arbitrary (read:infinite) length. This means that -1 is not 0xffffffff, but is instead an infinitely long binary sequence of 1s.
You can create the 32bit representation limit
def countOnes(num):
num = num % (1 << 32)
count = 0
while(num):
count += 1
num = num&(num-1)
return count

Finding if a number is a power of 2 using recursion

I'm trying to find whether a number is a power of 2 using recursion. However, I couldn't seem to figure out the correct solution. Here's what I've tried so far:
def is_power(n):
n = n/2
if n == 2:
return True
elif n > 2:
is_power(n)
else:
return False
if is_power(32):
print 'yes'
else:
print 'no'
Since '32' is a power of 2, I expected my code to return 'yes' as the output. However, the code outputs 'no' instead. What seems to be wrong with my code?
Since I already have an accepted answer here, I'll use this one to explain a bit why your approach is bad:
It uses recursion in python. Python needs to open up a stack frame for every call, so for very large numbers, this will be a bad way of solving this. It will even fail for very large integers.
I don't even think recursion in a non-purely-functional language like python is the intuitive thing to do here. There's a million easier ways to do this; for example, a while loop:
n = int(n)
while n>1:
if n/2 != n/2.0: #compare integer division to float division
return False
n = n/2
return True
Checking against power of two can be done in clever ways by realizing what the storage structure for integers on computers is: it's binary. So you could just count the binary 1s in your int's binary representation:
return bin(n).count('1') == 1
would also work. Of course, that would mean that python internally converts the integer to a string, which wastes memory on large numbers. So you might as well
power_of_2 = 1
while power_of_2 <= n:
if power_of_2 == n:
return True
power_of_2 *= 2
return False
simply compares your number to all smaller-or-equal powers of two. (which of course would probably take longer and use more memory, since your python interpreter will have to interpret python instead of just converting your integer to a string in C, but this is about algorithmic principles, right?) That way, you don't need to reserve memory just to count occurencies of 1 in your binary representation.
Of course, there's a one-liner that solves your issues, and I take it from the things I've learned writing in C/C++:
bool(n and not (n&(n-1)))
To explain n and not (n&(n-1)): n is True iff n != 0, which is would otherwise falsely qualify as power of 2.
For not (n&(n-1)): n&(n-1) checks whether something is not a power of 2, so we have to invert that. & is the bitwise "and" operator. To understand n & (n-1), imagine n is a power of 2, let's say 8. So n-1 == 7, and thus
8|0b1000
7|0b0111
--------
&|0b0000
as you can see, for all powers of two, n&(n-1) is 0, which evaluates to False. For all non-powers of two, you'll don't invert all the bits when subtracting 1, so n&(n-1) != 0, which evaluates to True.
elif n > 2:
is_power(n)
is missing the return:
def is_power(n):
n = n/2
if n == 2:
return True
elif n > 2:
return is_power(n)
else:
return False
thus, the "first" level of is_power returns nothing (or None, depending on how you check), which leads to output of no.
#kaveman correctly pointed out is_power(2) yields the wrong result.
You can fix that by halving 2 in the elif clause:
def is_power(n):
if not n == int(n):
return False
n = int(n)
if n == 1:
return True
elif n > 2:
return is_power(n/2.0)
else:
return False
EDIT: #will pointed out that I was mixing up python2 with python3 division. Using /2.0 fixes that. Also, in comments to the question he pointed out that 1 is a power of 2. Checking against ==1 instead of ==2 fixes that issue. Also, I added an int cast, which is not necessary for the power of 2 check (since well, IEEE754 floats are base 2 after all, so powers of 2 are exactly representable), but for non-2 bases, this will make the code portable.
The answer provided above is wrong.
Yes it will work for powers of two, but it will also give many false positives - as you are using integer division - because you are using python 2.7.
It would work if you were using from __future__ import division, which changes the behaviour of / - but this changes its behaviour throughout the program, which may not be what you want.
for example:
print 33/2 # 16
print 32/2 # 16
however, with from __future__ import division the outputs change to the correct (or at least more intuitive) results - to get the original integer math behaviour you need to use // instead (as in python3).
So the correct answer will be more like this:
def is_power(n):
n = n/2.0
if n == 2:
return True
elif n > 2:
return is_power(n)
else:
return False
Note the n= n/2.0 at the beginning.
You need to test your code works on several test cases, not just ones for which you want particular results.
Alternatively though, i would go with something like this:
def is_power(n):
if n == 2:
return True
elif n%2 != 0:
return False
else:
return is_power(n/2.0)
While this does not directly answer your question, the fastest way to implement this would be
def is_power(n):
return ((n & (n - 1)) == 0) and n != 0
While this has been covered in a previous post by Marcus, a 'bit' more explanation may help some. The binary representation of every number and the (number-1) share at least a single 1 bit, except if the number is a power of two. Further, all negative numbers share the leading bit, so are excluded by this method.
The only exception is the number 0, which doesn't share bits with the previous number -1, and may not be viewed as a power of 2. Therefore this needs an explicit check.
The binary table for the numbers will make this clear.
> Dcml Binary 5bit
> -15 10001
> -14 10010
> -13 10011
> -12 10100
> -11 10101
> -10 10110
> -9 10111
> -8 11000
> -7 11001
> -6 11010
> -5 11011
> -4 11100
> -3 11101
> -2 11110
> -1 11111
> 0 00000
> 1 00001
> 2 00010
> 3 00011
> 4 00100
> 5 00101
> 6 00110
> 7 00111
> 8 01000
> 9 01001
> 10 01010
> 11 01011
> 12 01100
> 13 01101
> 14 01110
> 15 01111
> 16 10000
No negative numbers in this signed number notation would satisfy the condition as they all share the most significant bit as 1. number 0 would satisfy the condition as 0&(any_other_number) == 0. If you need to implement this for very large numbers you may be better off using bitarrays or numpy with changed dtype. Also, this discussion may be helpful for speed of bitwise operations for on large arrays/numbers.
"""
Power check if a number is a power of 2
Negative numbers are not allowed
"""
import math
def is_power_of_two(num):
"""
:type num: integer
"""
try:
x=0
x = math.log10(num)/math.log10(2)
return 2 ** x == num
except ValueError:
exit()
You can just use the power of the math library
import math
def isPowerOfTwo(n):
if n <= 0:
return False
res = int(math.log(n) / math.log(2))
return 2 ** res == n
This was my solution for a function which checks which number is a base of another:
def is_power_of(number, base):
# when number is smaller than base.
if base <= 1:
return False
elif number < base:
return False
elif number > base:
# keep dividing number by base.
return is_power_of(number/base, base)
else:
return True
This will be bit informative,
counter = 0
def powoftwo(n):
global counter
counter+=1
if n%2 != 0:
return "Given Number %s is not Power of 2!"%g
else:
if n==2:
return "yes give number %s = 2**%s is power of 2!"%(g, counter)
return powoftwo(n/2)
g = 1024
print powoftwo(g)
yes give number 1024 = 2**10 is power of 2!
Late to the party, though yet, another way:
import math
def is_power_of_2(x):
n = math.log(abs(x), 2)
return n == int(n)

Categories

Resources