how many '1' in a 32-bits integer programmed with python - 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

Related

Python: Trying to Count Number of 1 Bits in an Integer But Missing One 1

Input: n = 00000000000000000000000000001011
Output: 3
Explanation: The input binary string 00000000000000000000000000001011 has a total of three '1' bits.
When I run my code below it appears that only two 1's are recognized ... why is that?
class Solution(object):
def hammingWeight(self, n):
"""
:type n: int
:rtype: int
"""
sum = 0
for i in str(n):
sum += int(i)
return sum
I think I'm misunderstanding some concepts here. Would appreciate some guidance.
Python 3.10 introduces int.bit_count() but if you have to implement the algorithm yourself then you can try something like this:
test.py:
def count(n):
bits = 0
while n:
bits += 1
n &= n - 1
return bits
def main():
n = 0b110001010000000000111
c = count(n)
print(f"Bit length: {n.bit_length()}, bits: {c}")
if __name__ == "__main__":
main()
Test:
$ python test.py
Bit length: 21, bits: 7
The time complexity of this algorithm is O(k) where k is the number of bits set to 1.
change str(n) into bin(n)[2:]. This way you will get binary representation string of n with omitted "0b" prefix.
BTW, you don't need to count manually in a loop. Python string has .count():
return bin(n).count("1")

Python XOR of all the bits of an integer

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".

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 can I reverse index and -1 each loop

value = input("Enter the binary value to convert to a decimal number.")
prod = 0
power = 0
ans = 0
for i in range (int(value)):
prod = ((int(value[*right most digit here*])) * ((2**power)))
ans = prod + ans
prod = 0
power + 1
else:
print (ans)
I am trying to create a binary calculator.
I believe I have the power part of the equation working as it begins with 2 ^ 0, then 2 ^ 1 for the next digit and so on. But I am having trouble getting the first part of the equation, the right most digit of the value inputted.
So let's say, 0101 was inputted. I want 1 * ( 2 ^ 0 ) in the first loop, 0 * ( 2 ^ 1) in the second loop, and so on; right to left. So with how indexing works in Python, how can I reverse index it so [4] is in the first loop, then [3] in the second loop, and so on.
Thanks for help.
However there are better options available, i am assuming you are clearing your basics. Following can be the options:
Note : You should use len(value) instead of int(value) in the loop.
# 1. When starting the loop from 0 (i.e. i=0). you can use ( len(value) - i )th index.'
for i in range (len(value)):
prod = ((int(value[len(value) - i - 1])) * ((2**power)))
ans = prod + ans
prod = 0
power = power + 1
# 2. Python also supports negative indexing, So you may run a loop from -1 to -len(value).
for i in range (-1,-len(value) - 1,-1):
prod = ((int(value[i])) * ((2**power)))
ans = prod + ans
prod = 0
power = power + 1
# 3. You can reverse the whole string in your first step and then loop from 0 to len(value)-1.
value = reversed(value)
for i in range (len(value)):
prod = ((int(value[i])) * ((2**power)))
ans = prod + ans
prod = 0
power = power + 1
But there are some bugs in the code (or may be lack on information). This code works only for unsigned integers. If you want it to work on signed numbers as well, you have to take 2's complement into consideration.
Below is a very simple code that works with signed numbers too (in case needed):
#convert binary string into decimal value. Works on 2's complement.
def binToDecimal(s):
neg = False
if s[0] == '1':
s = twosComp(s)
neg = True
#compute the decimal value
val = reduce(lambda x,y : int(x)*2+1 if y=='1' else int(x)*2,'0'+s)
#negate the value if the first bit is 1
return -val if neg else val
#return the 2's complement string
def twosComp(s):
s = list(s[::-1])
#take 1's complement
s = ['1' if i=='0' else '0' for i in s]
#take 2's complement
for i in range(len(s)):
if s[i] == '0':
#no carry will be generated in this case, so we break it.
s[i] = '1'
break
else:
s[i]='0'
# return 2's complement string
return ''.join(map(str,s))[::-1]
value = input("Enter the binary value to convert to a decimal number.")
power = 0
ans = 0
for i in reversed(value):
prod = int(i) * (2**power)
ans = prod + ans
power += 1
else:
print(ans)
Improved your code while keeping it as close to your code as possible. Your for loop was creating a list of 1 to whatever the value we input, that's not what you should be doing. One way of doing is, treating your input as a string (which basically is a list that can be iterated through) reverse it so you go from right to left, then do your operation on it on each value. You were trying to get the index of the location of the value input right? Why? Python is beautiful where you most likely don't need to directly tell the index of something.
value = input("Enter the binary value to convert to a decimal number.")
prod = 0
power = 0
ans = 0
for i in range(int(len(value))-1):
prod = ((int(value[-1])) * ((2**power)))
ans = prod + ans
prod = 0
power + 1
else:
print (ans)
You were doing the range of the value and not the input len so we use len() to get the length of the string that was inputted. -1 is there because the length of a string can be 3 for input 001 but if indexing 3 would be out of bounds because indexing starts at 0 not 1
Note that in Python a negative index value is accepted. Negative index means starts from the end of the list and count backwards, so I think that was the answer you were looking for.
For example if we have the list my_list=['a','b','c'] and we call my_list[-2] it will return 'b'
You have some mistakes in your code, so replace it with this:
value = input("Enter the binary value to convert to a decimal number: ")
value = int(value) # conversion from string to number
power = 0
ans = 0
while(value > 0):
lastDigit = value % 10 # last digit
value = value // 10 # cutting off last digit (for next iteration)
prod = lastDigit * (2 ** power)
ans = prod + ans
power = power + 1
print (ans)
Last digit is calculated as the remainder after division by 10 (value % 10)
and is cutting of by integer division by 10 (value // 10) - as in first grades of basic school: 27 % 10 = 7 27 // 10 = 2
Simpler way to achieve this with be to mention base as 2 with int(). For example:
>>> num = '110'
>>> int(num, 2)
6
In case you are looking for custom solution, you may create a function as:
def binary_string_to_int(binary_string):
int_num = 0
for i in binary_string:
int_num += int(i)
int_num *= 2
return int_num / 2
Sample run:
>>> binary_string_to_int('111')
7
>>> binary_string_to_int('101')
5

Categories

Resources