I encountered such a function:
import math
import random
def low_zeros(value):
for i in xrange(1, 32):
if value >> i << i != value:
break
return i - 1
I googled but not found any useful material about value >> i << i != value:
It's checking how many right-side bits are set to zero.
>> bitshifts right, then << bitshifts left by the same amount. Consider:
0b1000 >> 3 << 3
the first shift will do 0b1000 -> 0b0001. The second will do 0b0001 -> 0b1000. That's still equal to the original, so we're set.
Now let's see
0b1000 >> 4 << 4
the first shift will do 0b1000 -> 0b0000 because it shifts the one off the right side of the number. The second shift will try to shift back, but there's nothing to shift (0 << n == 0 for any natural number n). The function is left to compare 0 != 0b1000 and of course breaks execution of the for block.
The function then returns 4-1, which is 3, which is how many zeroes are on the right side of the number.
Related
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 11 months ago.
Improve this question
While I was reading a book, I found this example.
def apply_discount(product, discount):
price = int(product['price'] * (1.0 - discount))
assert 0 <= price <= product['price']
return price
I never saw the syntax 0 <= price <= product['price'] before, and it's clear that here it's testing the price, which should >= 0 and <= product['price']. I tested the function and it works as expected. I want to do more testing about the syntax 0 <= price <= product['price'].
a = 7
if 0 << a << 10:
print('a is greater than or equal to 0 and less than or equal to 10')
else:
print('a is not greater than or equal to 0 and less than or equal to 10')
It always prints a is not greater than or equal to 0 and less than or equal to 10. Why does it happen? What exactly does 0 << a << 10 work?
<< is a shift operator, you need to use < or <=:
a = 7
if 0 <= a <= 10:
print('a is greater than or equal to 0 and less than or equal to 10')
else:
print('a is not greater than or equal to 0 and less than or equal to 10')
<< is a bitwise operation that correspond to a left shift. A left shift is analogous to multiplying by two.
For example:
print(2 << 1)
# 4
print(2 << 2) # Do two left-shifts
# 8
In general, n << m will be equal to n * (2 ** m).
Now shifting has a left to right associativity so your condition will be interpreted as ((0 << a) << 10). Using the formula above, you'll notice that this will always give us 0, regardless of what the value of a is. 0 is equivalent to a boolean False so your condition will always be False
Your check uses bit-shifting, not comparison operations. It will always produce a falsey value.
<< is the left shift operator. It is not a comparison operation (use < or <= if you want comparison).
To see how this expression works, we evaluate the operations left to right. So, 0 << a << 10 is equivalent to (0 << a) << 10.
(0 << a) is 0 shifted over a bits, which is 0. a happens to be 7 here, but shifting 0 over by any number of bits would still produce zero.
0 << 10 is 0 shifted over 10 bits, which is still 0.
Zero is a falsey value, so the if check fails, and the else branch is executed.
Let's say I have a string representing a hexadecimal value such as "0x4", binary represented as 0100. If I want test whether the nth bit is set to 1, and where I count starting from the least significant bit (meaning in this example that only the 3rd bit is 1) how can I do this in the most elegant way?
I doubt the way I am doing is very elegant or efficient.
bits = '{0:08b}'.format(int(0x4, 16))
and then check if str(bits[-3]) is "1"
bits = '{0:08b}'.format(int(0x4, 16))
if str(bits[-3]) == "1":
print "Bit is set to 1"
I'd like a neat way of doing this, e.g. using bitwise operators or shifting.
To test if a bit is set, use the bitwise & on a bit mask of just that bit:
>>> bool(12 & 0b0100)
True
To get a bit mask set at the n-th position, bit-shift a 1 by n-1 positions:
>>> n = 3
>>> 1 << n-1
4
>>> bin(1 << n-1)
'0b100'
Combined, you can directly check whether a specific bit is set:
>>> def bitset(number, n):
... """Test whether ``number`` has the ``n``'th bit set"""
... return bool(number & 1 << n - 1)
...
>>> bitset(0x4, 3)
If your input is a string (instead of generating a string from an integer), use int to convert it:
>>> bitset(int('0x4', 16), 3)
Usually you'd use bitwise operators for that:
if 4 & 1 << n:
print('Bit', n, 'is set')
You could use the bin() function to convert an integer to a binary string:
>>> n = int('0x4', 16)
>>> n
4
>>> bin(n)
'0b100'
>>> bin(n)[-3] == '1'
True
A more efficient way would be to operate on the integer directly using bitwise operators:
>>> bool(n & 1<<2) # shift "1" 2 bits to the left and use bitwise and
True
you can use:
def check_nth_bit(str_hex, nth_bit):
return (int(str_hex, 16) & 2 **(nth_bit - 1)) >> (nth_bit - 1) == 1
print(check_nth_bit('0x4', 3))
print(check_nth_bit('0x4', 1))
output:
True
False
Please help in understanding the logic behind the following function:
def bit_rev (x, b): # reverse b lower bits of x
return sum (1<<(b-1-i) for i in range (0, b) if (x>>i) & 1)
I took a look at the code and it doesn't seem to account for bits past the b'th bit. So, I added another addition. (Unless all you want is up to the b'th bit):
def bit_rev (x, b): # reverse b lower bits of x
return (x >> b << b) + sum(1 << (b - 1 - i) for i in range (0, b) if (x >> i) & 1)
Now for the explaining the logic.
x >> b << b
So, let's say we're using 5 (as x) in this example with 2 as b.
The binary representation of 5 is 101. So, we want to switch only the last 2 bits. Which is 01. However, in our other code we are swapping them, but we are ignoring the bits past b. So, we are ignoring the first (from left to right) 1.
Now the first operations:
x >> b in our case is 5 >> 2. 101 moving to the right 2 is 1, since we end up chopping off the 01.
Next we shift it back. We are guaranteed (in Python) to get 0's back from the bit shift, so we now have 100, or 4.
Now for the meaty part,
sum(1 << (b - 1 - i) for i in range (0, b) if (x >> i) & 1)
It's probably would be easier to understand this outside of a list comprehension, so I rewrote it as a for-loop.
summation = 0
for i in range (0, b):
if (x >> i) & 1:
summation += 1 << (b - 1 - i)
Basically on each iteration we are finding the reverse bit an then adding it to the total (summation).
This code seems to be kind of difficult to understand because there is a lot going on.
Let's start with the for loop itself. for i in range (0, b) is iterating over all values between 0 and b. (Or the last bit you want to change). All the reversing happens later on in the code.
Next we check to see if the bit we are going to swap is a 1. In binary only 1's add value to the total number, so its logical to ignore all 0's. In if (x >> i) & 1:. We bitshift x to the right i bits. So, 101 bit shifted to the right 1 bit is 10. We now check to see if that last bit is a 1 by doing & 1. Basically what & 1 does in this program is ignore all bits beyond the first bit.
The and bitwise operator works as follows:
0101
&1100
=0100
And requires both to be true. Since all bits past 1 would be 0, it effectively ignores the rest.
Now we get a 0 or a 1 from (x >> i) & 1 and Python processes all non-zero integers as True and zero as False. This will make use ignore all bits that are zero.
Next, we add to summation using: summation += 1 << (b - 1 - i). We get the location of where it the bit is going to be by using b - 1 - i. Then we shift 1 over to that location and then add it to the total.
When adding two binary integers, you can add a 1 to a location in the number similar to how you would base 10. So, if I had the number 9000 and I wanted a 1 in the hundredths digit I could do 9000 + 100. That is similar to what we are doing here. We are moving it over to the left in base 2 by using the << operator instead of taking 10^i. So we are setting the newly reversed bit to whatever the original bit was.
I have the following code in Python:
for i in range(4):
if self.start == self.corners[i]:
self.visitedCorners += (1 << i)
I'm working with co-ordinates. self.start and self.corners are co-ordinates.
So with the code on the top I want to check whether the start is a corner.
If the start is the same of a corner, I do that shift. But, how does that shift work?
I don't want any other code; I just want to understand this code.
All that 1 << i does is produce the number with the i-th least significant bit set to 1 and all other bits set to 0:
>>> for i in range(4): print bin(1 << i)
...
0b1
0b10
0b100
0b1000
In the code, self.visitedCorners is a bit mask, where the four least significant bits correspond to the four corners. Each iteration of the for i loop sets the corresponding bit in self.visitedCorners to 1 (provided the if condition holds).
This is a follow-up to my question yesterday:
CMS kindly provided this example of using bitwise operators to add two numbers in C:
#include<stdio.h>
int add(int x, int y) {
int a, b;
do {
a = x & y;
b = x ^ y;
x = a << 1;
y = b;
} while (a);
return b;
}
int main( void ){
printf( "6 + 3 = %d", add(6,3));
printf( "6 - 3 = %d", add(6,-3));
return 0;
}
It works great and I then ported it to Python as follows:
def add(x, y):
while True:
a = x & y
b = x ^ y
x = a << 1
y = b
if a == 0:
break
return b
print "6 + 3 = %d" % add(6,3)
print "6 - 3 = %d" % add(6,-3)
They both work for addition and the C program works for subtraction as well. However, the Python program enters an infinite loop for subtraction. I am trying to get to the bottom of this and have posted the program here for further experimentation: http://codepad.org/pb8IuLnY
Can anyone advise why there would be a difference between the way C handles this and the way CPython handles this?
As I pointed out in my response to CMS' answer yesterday, left-shifting a negative number is undefined behavior in C so this isn't even guaranteed to work in C (the problem is how to handle the signed bit, do you shift it like a value bit or is it not affected by a shift? The standards committee couldn't agree on a behavior so it was left undefined).
When this happens to work in C it relies on fixed bit-width integers so that the leftmost bit gets pushed off the end when you do a shift (it also requires the sign bit to be treated as a value bit for shifting purposes). All integer types in C are fixed-bit but Python numbers can be arbitrarily large. Left-shifting a number in Python just causes it to keep getting larger:
>>> 1 << 100
1267650600228229401496703205376L
You could try something like this:
x = (a << 1) & 0xffffffff
To limit the result to 32-bits, the problem is that the left shift operator in Python doesn't shift the sign bit of a signed number (which is part of what is required to make this particular solution work). There might be a way to change the behavior of the shift operator but I don't know how.
Shifting negative numbers doesn't have consistent interpretation between python and C.
if i, j are two integers:
addition:
printf("%d",(i^j)|((i&j)<<1));
I've noticed that you're assuming that python works with numbers the same way as C does.
Thats not entirely true. Meaning C's int numbers have a fixed length of 16 bits. For detailed info on C datatypes you can refer to C_data_types on en.wikipedia.org
Python, on the other hand, is said to have a virtually infinite length for int numbers.
Adding positive integers may work the same way. But subtracting or adding negative integers shouldn't be a simple mapping translation.
An easy way to understand this is a little example on negative numbers:
Imagine a fixed length integer representation of 3 bits:
#Unsigned#
000 : 0
001 : 1
010 : 2
011 : 3
100 : 4
101 : 5
110 : 6
111 : 7
#Signed:#
000 : 0
001 : 1
010 : 2
011 : 3
100 : -4
101 : -3
110 : -2
111 : -1
This works cool because you can see that 1-3=1+(-3), -3 is 101 that's 5 if unsigned. So 1+5=6, 6 : 110 : -2. This means that 1-3=-2.
it also becomes buggy when overflowing:
-4 + -1 = 3 not -5 because it's out of range!
3 + 1 = -4 not 4 because it's out of range!
As you may see this works for fixed length but it doesn't work this way in Python.
For anyone are still interested, to resolve issue in python, just add a new case and switch the order of x and y inside the function, and return the negative value, though this put "-" in the function, but this presented a way using bit-wise operator. For anyone still wish to argue using operator "-" in the following question, I could argue that for the case of 2 - 6, the right answer is -4 where "-" exists in the answer, so it might be okay to add it when x is smaller than y. Hope this helps.
#A substract to substract two integers using bits operators
#refer to: https://www.geeksforgeeks.org/subtract-two-numbers-without-using-arithmetic-operators/
def subtractBits(x, y):
xRAW = x
yRAW = y
if x < y:
x = y
y = xRAW
# Iterate till there
# is no carry
while (y != 0):
# borrow contains common
# set bits of y and unset
# bits of x
borrow = (~x) & y
# Subtraction of bits of x
# and y where at least one
# of the bits is not set
x = x ^ y
# Borrow is shifted by one
# so that subtracting it from
# x gives the required sum
y = borrow << 1
if xRAW < yRAW:
return -x
else:
return x
print(subtractBits(100, 50))
print(subtractBits(1, 3))
print(subtractBits(40, 0))
print(subtractBits(0, 40))
print(subtractBits(5, 5))