Can someone please explain the purpose of the bitwise, Binary AND Operator( & ) and how to use it? I was looking at different ways of making a isprime function and came across this.
def isprime(n):
# make sure n is a positive integer
n = abs(int(n))
# 0 and 1 are not primes
if n < 2:
return False
# 2 is the only even prime number
if n == 2:
return True
# all other even numbers are not primes
if not n & 1:
return False
# range starts with 3 and only needs to go up the squareroot of n
# for all odd numbers (counts by 2's)
for x in range(3, int(n**0.5)+1, 2):
if n % x == 0:
return False
return True
I also looked at Python Bitwise Operators Example but couldn't grasp it.
One number AND another is the bits of one number masked by the bits of another number. If a number AND 1 is 0 (not n & 1 would be True), that means it's divisible by two, since all multiples of 2 have a 0 as the rightmost binary digit.
11 = 00001011 (Not divisible by 2) 28 = 00011100 (Divisible by 2)
& 1 = 00000001 & 1 = 00000001
--------------- ---------------
00000001 00000000
For example,
12 & 7 =
1100 & 0111
= 0100
= 4
For the isPrime function, the first condition checks whether it is 0 or 1. The second condition checks whether it is 2. The third condition then checks if (n&1), which is a check whether the number is even. Every even number when converted to binary form has 0 in its last digit. So for example,
14 & 1 =
1110 & 0001
= 0
14 is proved to be even and henceforth not prime.
Related
Basically trying to learn Python and I was doing the hackerrank 30 day challenge.
Task
Given an integer, n , perform the following conditional actions:
If n is odd, print ok
If n is even and in the inclusive range of 2 to 5, print nok
n = 4
if n in range(2,5) and type(n/2) == int:
print ("ok")
else:
print ("nok")
it prints "nok" no matter what n is.
In Python 3 / always returns a float (isinstance(4 / 2, int) is False since 4 / 2 returns 2.0).
Since you are essentially checking for the parity of n, check it explicitly:
... and n % 2 == 0:
Because, n/2 = 2.0 not 2, i.e division returns a float not int here are some ways to check it :
n in range(2,5) and n % 2 == 0
#or
n in range(2,5) and n & 1 != 1 #because, every odd number has last bit 1
The code below isn't working right for some inputs.
a, i = set(), 1
while i <= 10000:
a.add(i)
i <<= 1
N = int(input())
if N in a:
print("True")
else:
print("False")
My initial idea was to check for each input if it's a power of 2 by starting from 1 and multiplying by 2 until exceeding the input number, comparing at each step. Instead, I store all the powers of 2 in a set beforehand, in order to check a given input in O(1). How can this be improved?
Bit Manipulations
One approach would be to use bit manipulations:
(n & (n-1) == 0) and n != 0
Explanation: every power of 2 has exactly 1 bit set to 1 (the bit in that number's log base-2 index). So when subtracting 1 from it, that bit flips to 0 and all preceding bits flip to 1. That makes these 2 numbers the inverse of each other so when AND-ing them, we will get 0 as the result.
For example:
n = 8
decimal | 8 = 2**3 | 8 - 1 = 7 | 8 & 7 = 0
| ^ | |
binary | 1 0 0 0 | 0 1 1 1 | 1 0 0 0
| ^ | | & 0 1 1 1
index | 3 2 1 0 | | -------
0 0 0 0
-----------------------------------------------------
n = 5
decimal | 5 = 2**2 + 1 | 5 - 1 = 4 | 5 & 4 = 4
| | |
binary | 1 0 1 | 1 0 0 | 1 0 1
| | | & 1 0 0
index | 2 1 0 | | ------
1 0 0
So, in conclusion, whenever we subtract one from a number, AND the result with the number itself, and that becomes 0 - that number is a power of 2!
Of course, AND-ing anything with 0 will give 0, so we add the check for n != 0.
math functions
You could always use math functions, but notice that using them without care could cause incorrect results:
math.log(x[, base]) with base=2:
import math
math.log(n, 2).is_integer()
math.log2(x):
math.log2(n).is_integer()
Worth noting that for any n <= 0, both functions will throw a ValueError as it is mathematically undefined (and therefore shouldn't present a logical problem).
math.frexp(x):
abs(math.frexp(n)[0]) == 0.5
As noted above, for some numbers these functions are not accurate and actually give FALSE RESULTS:
math.log(2**29, 2).is_integer() will give False
math.log2(2**49-1).is_integer() will give True
math.frexp(2**53+1)[0] == 0.5 will give True!!
This is because math functions use floats, and those have an inherent accuracy problem.
(Expanded) Timing
Some time has passed since this question was asked and some new answers came up with the years. I decided to expand the timing to include all of them.
According to the math docs, the log with a given base, actually calculates log(x)/log(base) which is obviously slow. log2 is said to be more accurate, and probably more efficient. Bit manipulations are simple operations, not calling any functions.
So the results are:
Ev: 0.28 sec
log with base=2: 0.26 sec
count_1: 0.21 sec
check_1: 0.2 sec
frexp: 0.19 sec
log2: 0.1 sec
bit ops: 0.08 sec
The code I used for these measures can be recreated in this REPL (forked from this one).
Refer to the excellent and detailed answer to "How to check if a number is a power of 2" — for C#. The equivalent Python implementation, also using the "bitwise and" operator &, is this:
def is_power_of_two(n):
return (n != 0) and (n & (n-1) == 0)
As Python has arbitrary-precision integers, this works for any integer n as long as it fits into memory.
To summarize briefly the answer cited above: The first term, before the logical and operator, simply checks if n isn't 0 — and hence not a power of 2. The second term checks if it's a power of 2 by making sure that all bits after that bitwise & operation are 0. The bitwise operation is designed to be only True for powers of 2 — with one exception: if n (and thus all of its bits) were 0 to begin with.
To add to this: As the logical and "short-circuits" the evaluation of the two terms, it would be more efficient to reverse their order if, in a particular use case, it is less likely that a given n be 0 than it being a power of 2.
In binary representation, a power of 2 is a 1 (one) followed by zeros. So if the binary representation of the number has a single 1, then it's a power of 2. No need here to check num != 0:
print(1 == bin(num).count("1"))
The bin builtin returns a string "0b1[01]?" (regex notation) for every strictly positive integer (if system memory suffices, that is), so that we can write the Boolean expression
'1' not in bin(abs(n))[3:]
that yields True for n that equals 0, 1 and 2**k.
1 is 2**0 so it is unquestionably a power of two, but 0 is not, unless you take into account the limit of x=2**k for k → -∞. Under the second assumption we can write simply
check0 = lambda n: '1' not in bin(abs(n))[3:]
and under the first one (excluding 0)
check1 = lambda n: '1' not in bin(abs(n))[3:] and n != 0
Of course the solution here proposed is just one of the many possible ones that
you can use to check if a number is a power of two... and for sure not the most
efficient one but I'm posting it in the sake of completeness :-)
Note: this should be a comment on Tomerikoo's answer (currently the most upvoted) but unfortunately Stack Overflow won't let me comment due to reputation points.
Tomerikoo's answer is very well explained and thought-out. While it covers most applications, but I believe needs a slight modification to make it more robust against a trivial case. Their answer is:
(n & (n-1) == 0) and n != 0
The second half checks if the input is an actual 0 which would invalidate the bitwise-and logic. There is another one trivial case when this could happen: input is 1 and the bitwise-and takes place with 0 again, just on the second term. Strictly speaking, 2^0=1 of course but I doubt that it's useful for most applications. A trivial modification to account for that would be:
(n & (n-1) == 0) and (n != 0 and n-1 != 0)
The following code checks whether n is a power of 2 or not:
def power_of_two(n):
count = 0
st = str(bin(n))
st = st[2:]
for i in range(0,len(st)):
if(st[i] == '1'):
count += 1
if(count == 1):
print("True")
else:
print("False")
Many beginners won't know how code like (n != 0) and (n & (n-1) == 0) works.
But if we want to check whether a number is a power of 2 or not, we can convert the number to binary format and see it pretty clearly.
For Example:
^ (to the power of)
2^0 = 1 (Bin Value : 0000 0001)
2^1 = 2 (Bin Value : 0000 0010)
2^2 = 4 (Bin Value : 0000 0100)
2^3 = 8 (Bin Value : 0000 1000)
2^4 = 16 (Bin Value : 0001 0000)
2^5 = 32 (Bin Value : 0010 0000)
2^6 = 64 (Bin Value : 0100 0000)
2^7 = 128 (Bin Value : 1000 0000)
If you look at the binary values of all powers of 2, you can see that there is only one bit True. That's the logic in this program.
So If we count the number of 1 bit's in a binary number and if it is equal to 1, then the given number is power of 2, otherwise it is not.
n = int(input())
if '1' in list(bin(n))[3:]: #also can use if '1' in bin(n)[3:] OR can also use format(n, 'b')[1:]
print("False")
else:
print("True")
For every number which is power of 2 say(N = 2^n), where n = +integer bin(N)=bin(2^(+int)) will have string of form: 0b10000000 e.i 0b1.....zero only if not 0, N is not power of 2.
Also, format(n, 'b') returns bin(n)[2:] so can be used
Source
>>> format(14, '#b'), format(14, 'b')
('0b1110', '1110')
>>> f'{14:#b}', f'{14:b}'
('0b1110', '1110')
Use *2 instead of bit shifts. Multiplication or addition are much more readable.
In python 3.10, int.bit_count counts the set bits of a number, so we can use
n.bit_count() == 1
Most of the above answers use bin() of format(int(input()), "b")
The below code also works: Ev(x) returns True if x is power of 2
# Ev(x) ~ ispoweroftwo(x)
def Ev(x):
if x==2: return True
elif x%2: return False
return Ev(x//2)
The above code is based on generating bin()
#This function returns binary of integers
def binary(x):
a = ""
while x!= 0:
a += str(x%2)
x = x//2
return a[::-1]
I = int(input())
print(format(I, "b")) # To cross-check if equal of not
print(binary(I))
I have tried to add my answer because I found what we are doing using bin(x)[3:] or format(x, "b") is almost like asking the boolean answer of whether or not a given number x is divisible by two.....and we keep asking the same
Given a binary number, I need to write a function to count the total steps reaching zero. The rules are:
If the number is even, divide it by 2
If the number is odd, subtract 1 from it
for example, it takes six iterations for "1110" (14) to become 0:
14 / 2 = 7
7 - 1 = 6
6 / 2 = 3
3 - 1 = 2
2 / 2 = 1
1 - 1 = 0
I have come up with a naive solution that does calculations, but this algorithm cannot handle numbers that are very large.
def test(x):
a = int(x,2)
steps = 0
while a != 0:
if a % 2 == 0:
a = a // 2
else:
a = a - 1
steps += 1
return steps
test("1000")
Out[65]: 4
test("101")
Out[66]: 4
test("001")
Out[67]: 1
test("0010010001")
Out[68]: 10
test("001001")
Out[69]: 5
what I need to know: How can I avoid doing the calculation and have an algorithm that is fast / can handle big numbers?
Assuming your code is correct and the rule is:
test(0) = 0
test(n) = 1 + test(n / 2) if n is even;
1 + test(n − 1) otherwise
the important thing to notice is that:
an even number ends with a binary 0
dividing by 2 removes the 0 from the end (and nothing else)
an odd number ends with a binary 1
subtracting 1 turns the last 1 to a 0 (and nothing else)
So every 1 bit except for the first one adds 2 steps, and every significant 0 bit adds 1 step. That means for inputs that start with 1, you can write:
def test(x):
return x.count('1') + len(x) - 1
Now you just need to account for leading zeros, or just the specific case of "0" if leading zeros aren’t possible.
I had this question on a coding test today, I had 40 mins to complete the test. Unfortunately, I only came up with a good solution after the timer had reached the limit.
You do not need to calculate the divisions and the subtractions(!). You can iterate over the characters of S, if the character is a 1, two steps are required, if the character is a 0, only one step is required.
If there is a 1 at the end, you will subtract 1
If there is a 0 at the end, you can divide by two and the number will shift to the right.
The first character is an exception (S[0])
Here is the solution:
def iterate_string(S: str):
acc = 0
for c in S:
if c == "0":
acc += 1
else:
acc += 2
acc -= 1 # the very first 1 is only + 1, thus - 1
return acc
Here is an example:
1001 (17) - 1 = 1000 (16)
1000 (16) / 2 = 100 (8)
100 (8) / 2 = 10 (4)
10 (4) / 2 = 1
1 - 1 = 0
# First digit, requires two steps:
|
1001
# Second digit, requires one step:
|
1001
# Third digit, requires one step:
|
1001
# S[0] is 1, but requires only one step:
|
1001
=> total of 5 steps:
0: 1001 # (-1)
1: 1000 # (/2)
2: 100 # (/2)
3: 10 # (/2)
4: 1 # (-1)
5: 0
Good luck to the next person who is having the same challenge! :)
Here is the naive solution that can't handle big numbers:
def do_calculations(S: str):
decimal_value = int(S, 2)
iterations = 0
while decimal_value > 0:
if decimal_value % 2 == 1:
decimal_value = decimal_value - 1
else:
decimal_value = decimal_value / 2
iterations += 1
return iterations
Your algorithm isn't correct for odd numbers. You are only dividing when the number is even, which is not how you described the "steps."
you want
def test(x, 2):
x_int = int(x)
steps = 0
while x_int <= 0:
x_int //= 2
x -= 1
steps += 1
You should clarify your algorithm, because the way you described it, you're not guaranteed to converge to 0 for all inputs. The way you described it is an infinite loop for odd numbers. Just try 1:
#test(1)
1 // 2 = 0
0 - 1 = -1
...
Now you will never get to 0, which is why you should check for x_int <= 0.
I suggest you reconsider why you want to do this anyway. I'm fairly certain that you don't even need an iterative algorithm to know how many "steps" are required anyway, there should just be a mathematical formula for this.
You could also use a recursive approach:
def stepsToZero(N):
return N if N < 2 else 2 + stepsToZero(N//2-1)
This will get you results up to N = 2**993 (which is quite a big number) with a very concise (and imho more elegant) function.
What would run much faster would be to solve this mathematically
For example:
import math
def steps2Zero(N):
if N < 2: return N
d = int(math.log(N+2,2))-1
s = int(N >= 3*2**d-2)
return 2*d+s
Note that, for N=2^900, the mathematical solution is a hundred times faster than the recursion. On the other hand, the recursive function responds in well under a second and is a lot more readable. So, depending on how this would be used and on what size numbers, performance considerations are likely pointless
If the input number is in binary (or convert the input number to binary) then implement this function simply
def solution(s): # 's' should be a binary input (011100)
while s[0] == "0":
s = s[1:]
ones = s.count('1')
zeros = s.count('0')
return ones*2+zeros-1
To check whether a number is a multiple of 4 or not without using +, -, * ,/ and % operators.
def multipleFour(n):
if n == 1:
return False
XOR = 0
for i in range(n):
XOR = XOR ^ 1
return XOR == n
multipleFour(20)
My answer returns False
You are mistaken in your for loop as well as xor statement. It should be like -
def multipleFour(n):
if n == 1:
return False
XOR = 0
for i in range(1, n+1):
XOR = XOR ^ i
return XOR == n
multipleFour(20)
i.e. your loop must run for i=1 to i=n and not i=0 to i=n-1. And it must be xor = xor ^ i
EDIT:
As pointed out in comments, for i in range(1, n+1) does not meet the condition of not using +, but by little modification, this thing can be solved as -
def multipleFour(n):
if n == 1:
return False
XOR = n
for i in range(1, n):
XOR = XOR ^ i
return XOR == n
multipleFour(20)
Your XOR starts with 0, and the only operation you ever employ on it is XOR ^ 1; the result can only ever be 0 or 1. Your code explicitly returns False on 1, and can't return True on any larger number; it should only return True for 0.
Meanwhile, it is very easy to check whether something is multiple of 4 "without using +, -, * ,/ and % operators.", using AND and NOT:
def multipleFour(n):
return not(n & 3)
You could check the binary and avoid xoring all integers from 0 to n:
0 0000
1 0001
2 0010
3 0011
4 0100 8 1000 12 1100
The binary signature of a multiple of four is '00'
def x_of_4(n):
return bin(n)[-2:] == '00'
However, although converting to a string makes it easy to visualize and understand, it is not the best of ideas, and this method fails for n = 0.
A better way to do the same is to bitwise-and-with 3 which will test the final two zeros of the binary representation (credits to #ShadowRanger in the comments:
def x_of_4(n):
return not n & 3
This question already has answers here:
Fast prime factorization module
(7 answers)
Closed 5 years ago.
I'm trying to get a fast way to determine if a number is prime using Python.
I have two functions to do this. Both return either True or False.
Function isPrime1 is very fast to return False is a number is not a prime. For example with a big number. But it is slow in testing True for big prime numbers.
Function isPrime2 is faster in returning True for prime numbers. But if a number is big and it is not prime, it takes too long to return a value. First function works better with that.
How can I come up with a solution that could quickly return False for a big number that is not prime and would work fast with a big number that is prime?
def isPrime1(number): #Works well with big numbers that are not prime
state = True
if number <= 0:
state = False
return state
else:
for i in range(2,number):
if number % i == 0:
state = False
break
return state
def isPrime2(number): #Works well with big numbers that are prime
d = 2
while d*d <= number:
while (number % d) == 0:
number //= d
d += 1
if number > 1:
return True
else:
return False`
Exhaustive division until the square root is about the simplest you can think of. Its worst case is for primes, as all divisions must be performed. Anyway, until a billion, there is virtually no measurable time (about 1.2 ms for 1000000007).
def FirstPrimeFactor(n):
if n & 1 == 0:
return 2
d= 3
while d * d <= n:
if n % d == 0:
return d
d= d + 2
return n
Note that this version returns the smallest divisor rather than a boolean.
Some micro-optimizations are possible (such as using a table of increments), but I don' think they can yield large gains.
There are much more sophisticated and faster methods available, but I am not sure they are worth the fuss for such small n.
Primality tests is a very tricky topic.
Before attempting to speed up your code, try to make sure it works as intended.
I suggest you start out with very simple algorithms, then build from there.
Of interest, isPrime2 is flawed. It returns True for 6, 10, 12, ...
lines 3 to 6 are very telling
while d*d <= number:
while (number % d) == 0:
number //= d
d += 1
When a factor of number d is found, number is updated to number = number // d and at the end of the while loop, if number > 1 you return True
Working through the code with number = 6:
isPrime2(6)
initialise> number := 6
initialise> d := 2
line3> check (2 * 2 < 6) :True
line4> check (6 % 2 == 0) :True
line5> update (number := 6//2) -> number = 3
line6> update (d : d + 1) -> d = 3
jump to line3
line3> check (3 * 3 < 3) :False -> GOTO line7
line7> check(number > 1) -> check(3 > 1) :True
line8> return True -> 6 is prime
Here is what I came up with
def is_prime(number):
# if number is equal to or less than 1, return False
if number <= 1:
return False
for x in range(2, number):
# if number is divisble by x, return False
if not number % x:
return False
return True