Last active
December 22, 2019 07:03
-
-
Save lfalanga/2f5b1226948862b435b40559c687406a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Example 1: Basic bitwise operations | |
print 5 >> 4 # Right Shift | |
# => 0 | |
print 5 << 1 # Left Shift | |
# => 10 | |
print 8 & 5 # Bitwise AND | |
# => 0 | |
print 9 | 4 # Bitwise OR | |
# => 13 | |
print 12 ^ 42 # Bitwise XOR | |
# => 38 | |
print ~88 # Bitwise NOT | |
# => -89 | |
# Example 2: The Base 2 Number System | |
""" | |
NOTE: | |
When we count, we usually do it in base 10. That means that each place in a | |
number can hold one of ten values, 0-9. In binary we count in base two, where | |
each place can hold one of two values: 0 or 1. The counting pattern is the same | |
as in base 10 except when you carry over to a new column, you have to carry | |
over every time a place goes higher than one (as opposed to higher than 9 in | |
base 10). | |
For example, the numbers one and zero are the same in base 10 and base 2. But | |
in base 2, once you get to the number 2 you have to carry over the one, | |
resulting in the representation “10”. Adding one again results in “11” (3) and | |
adding one again results in “100” (4). | |
Contrary to counting in base 10, where each decimal place represents a power of | |
10, each place in a binary number represents a power of two (or a bit). The | |
rightmost bit is the 1’s bit (two to the zero power), the next bit is the 2’s | |
bit (two to the first), then 4, 8, 16, 32, and so on. | |
The binary number ‘1010’ is 10 in base 2 because the 8’s bit and the 2’s bit | |
are “on”: | |
8's bit 4's bit 2's bit 1's bit | |
1 0 1 0 | |
8 + 0 + 2 + 0 = 10 | |
In Python, you can write numbers in binary format by starting the number with | |
0b. When doing so, the numbers can be operated on like any other number! | |
""" | |
print 0b1, #1 | |
print 0b10, #2 | |
print 0b11, #3 | |
print 0b100, #4 | |
print 0b101, #5 | |
print 0b110, #6 | |
print 0b111 #7 | |
print "******" | |
print 0b1 + 0b11 | |
print 0b11 * 0b11 | |
""" Printed out result | |
1 2 3 4 5 6 7 | |
****** | |
4 | |
9 | |
""" | |
# Example 3: Couting in binary | |
""" | |
NOTE: | |
2 ** 0 = 1 | |
2 ** 1 = 2 | |
2 ** 2 = 4 | |
2 ** 3 = 8 | |
2 ** 4 = 16 | |
2 ** 5 = 32 | |
2 ** 6 = 64 | |
2 ** 7 = 128 | |
2 ** 8 = 256 | |
2 ** 9 = 512 | |
2 ** 10 = 1024 | |
""" | |
one = 0b1 | |
two = 0b10 | |
three = 0b11 | |
four = 0b100 | |
five = 0b101 | |
six = 0b110 | |
seven = 0b111 | |
eight = 0b1000 | |
nine = 0b1001 | |
ten = 0b1010 | |
eleven = 0b1011 | |
twelve = 0b1100 | |
# Example 4: Using bin() funtion to get a binary representation of the number | |
print bin(1) | |
print bin(2) | |
print bin(3) | |
print bin(4) | |
print bin(5) | |
""" Printed out result | |
0b1 | |
0b10 | |
0b11 | |
0b100 | |
0b101 | |
""" | |
# Example 5: Getting the base 10 equivalent using int() function | |
print int("1",2) | |
print int("10",2) | |
print int("111",2) | |
print int("0b100",2) | |
print int(bin(5),2) | |
# Print out the decimal equivalent of the binary 11001001. | |
print int("11001001",2) | |
""" Printed out result | |
1 | |
2 | |
7 | |
4 | |
5 | |
201 | |
""" | |
# Example 6: Shift operators (<< and >>) | |
""" | |
NOTE: | |
Shift operations are similar to rounding down after dividing and multiplying | |
by 2 (respectively) for every time you shift, but it’s often easier just to | |
think of it as shifting all the 1s and 0s left or right by the specified number | |
of slots. | |
Note that you can only do bitwise operations on an integer. Trying to do them | |
on strings or floats will result in nonsensical output! | |
""" | |
# Left Bit Shift (<<) | |
0b000001 << 2 == 0b000100 (1 << 2 = 4) # = 1 * 2 * 2 = 1 * (2^2) | |
0b000101 << 3 == 0b101000 (5 << 3 = 40) # = 5 * 2 * 2 * 2 = 5 * (2^3) | |
# Right Bit Shift (>>) | |
0b0010100 >> 3 == 0b000010 (20 >> 3 = 2) # = 20 / 2 / 2 / 2 = 20 / (2^3) | |
0b0000010 >> 2 == 0b000000 (2 >> 2 = 0) # = 2 / 2 / 2 = 2 / (2^2) | |
# Example 7: Shifting binary numbers | |
shift_right = 0b1100 | |
shift_left = 0b1 | |
# Your code here! | |
shift_right = shift_right >> 2 | |
shift_left = shift_left << 2 | |
print bin(shift_right) | |
print bin(shift_left) | |
""" Printed out result | |
0b11 | |
0b100 | |
""" | |
# Example 8: AND (&) operation | |
""" | |
NOTE: | |
The bitwise AND (&) operator compares two numbers on a bit level and returns a | |
number where the bits of that number are turned on if the corresponding bits | |
of both numbers are 1. For example: | |
a: 00101010 42 | |
b: 00001111 15 | |
=================== | |
a & b: 00001010 10 | |
As you can see, the 2’s bit and the 8’s bit are the only bits that are on in | |
both a and b, so a & b only contains those bits. Note that using the & operator | |
can only result in a number that is less than or equal to the smaller of the | |
two values. | |
0 & 0 = 0 | |
0 & 1 = 0 | |
1 & 0 = 0 | |
1 & 1 = 1 | |
Therefore, | |
0b111 (7) & 0b1010 (10) = 0b10 | |
""" | |
print bin(0b1110 & 0b101) | |
# => 0b100 | |
print 0b1110 & 0b101 | |
# => 4 | |
# Example 9: OR (|) operation | |
""" | |
NOTE: | |
The bitwise OR (|) operator compares two numbers on a bit level and returns a | |
number where the bits of that number are turned on if either of the | |
corresponding bits of either number are 1. For example: | |
a: 00101010 42 | |
b: 00001111 15 | |
================ | |
a | b: 00101111 47 | |
Note that the bitwise | operator can only create results that are greater than | |
or equal to the larger of the two integer inputs. | |
So remember, for every given bit in a and b: | |
0 | 0 = 0 | |
0 | 1 = 1 | |
1 | 0 = 1 | |
1 | 1 = 1 | |
Meaning | |
110 (6) | 1010 (10) = 1110 (14) | |
""" | |
print bin(0b1110 | 0b101) # => 0b1111 | |
print 0b1110 | 0b101 # => 15 | |
# Example 10: XOR (^) operation | |
""" | |
NOTE: | |
The XOR (^) or exclusive or operator compares two numbers on a bit level and | |
returns a number where the bits of that number are turned on if either of the | |
corresponding bits of the two numbers are 1, but not both. | |
a: 00101010 42 | |
b: 00001111 15 | |
================ | |
a ^ b: 00100101 37 | |
Keep in mind that if a bit is off in both numbers, it stays off in the result. | |
Note that XOR-ing a number with itself will always result in 0. | |
So remember, for every given bit in a and b: | |
0 ^ 0 = 0 | |
0 ^ 1 = 1 | |
1 ^ 0 = 1 | |
1 ^ 1 = 0 | |
Therefore: | |
111 (7) ^ 1010 (10) = 1101 (13) | |
""" | |
print bin(0b1110 ^ 0b101) # => 0b1011 | |
print 0b1110 ^ 0b101 # => 11 | |
# Example 11: NOT (~) operation | |
""" | |
NOTE: | |
The bitwise NOT operator (~) just flips all of the bits in a single number. | |
What this actually means to the computer is actually very complicated, so we’re | |
not going to get into it. Just know that mathematically, this is equivalent to | |
adding one to the number and then making it negative. | |
And with that, you’ve seen all of the basic bitwise operators! We’ll see what | |
we can do with these in the next section. | |
""" | |
print ~1 | |
print ~2 | |
print ~3 | |
print ~42 | |
print ~123 | |
print ~-1 | |
print ~-2 | |
""" Printed out result | |
-2 | |
-3 | |
-4 | |
-43 | |
-124 | |
0 | |
1 | |
""" | |
# Example 12: Bit masking | |
""" | |
A bit mask is just a variable that aids you with bitwise operations. A bit mask | |
can help you turn specific bits on, turn others off, or just collect data from | |
an integer about which bits are on or off. | |
""" | |
num = 0b1100 | |
mask = 0b0100 | |
desired = num & mask | |
if desired > 0: | |
print "Bit was on" | |
def check_bit4(input): | |
if input & 0b1000 == 0b1000: | |
return 'on' | |
else: | |
return 'off' | |
# Example 13: Turning on a bit using OR (|) | |
""" | |
NOTE: | |
You can also use masks to turn a bit in a number on using |. For example, let’s | |
say I want to make sure the rightmost bit of number a is turned on. I could do | |
this: | |
a = 0b110 # 6 | |
mask = 0b1 # 1 | |
desired = a | mask # 0b111, or 7 | |
Using the bitwise | operator will turn a corresponding bit on if it is off and | |
leave it on if it is already on. | |
""" | |
a = 0b10111011 | |
mask = 0b00000100 | |
print bin(a | mask) # => 0b10111111 | |
# Example 14: Flipping bits using XOR (^) | |
""" | |
Using the XOR (^) operator is very useful for flipping bits. Using ^ on a bit | |
with the number one will return a result where that bit is flipped. | |
For example, let’s say I want to flip all of the bits in a. I might do this: | |
a = 0b110 # 6 | |
mask = 0b111 # 7 | |
desired = a ^ mask # 0b1 | |
""" | |
a = 0b11101110 | |
mask = 0b11111111 # This mask will flip all the bits in 'a' variable | |
print bin(a ^ mask) | |
# => 0b10001 | |
# Example 15: Slip and Slide | |
""" | |
Finally, you can also use the left shift (<<) and right shift (>>) operators | |
to slide masks into place. | |
a = 0b101 | |
# Tenth bit mask | |
mask = (0b1 << 9) # One less than ten | |
desired = a ^ mask | |
Let’s say that I want to turn on the 10th bit from the right of the integer a. | |
Instead of writing out the entire number, we slide a bit over using the << | |
operator. | |
We use 9 because we only need to slide the mask nine places over from the first | |
bit to reach the tenth bit. | |
""" | |
def flip_bit(number, n): | |
mask = (0b1 << (n-1)) | |
result = number ^ mask | |
return bin(result) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment