Bitwise Operators in Python - Tutorial & Application Fields

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] what is going on guys welcome back in today's video we're going to cover bitwise operators in python and this is usually one of those topics that i like to skip when i teach programming be it in a course be it in a video be it in a book i usually talk about all the other operators but i usually skip on the bitwise operators because they're too confusing for beginners so i mentioned that they exist i mentioned what they're basically used for but then we just skip them and we proceed with the rest of the beginner fundamental content and i think this is good because for beginners actually bitwise operators are confusing and they're not very useful because they're not going to need them for quite some time but what happens oftentimes is that people then never learn about them at least when they watch my content because we skip that and then we never catch up on it maybe we use it in a project but we don't really cover what bitwise operators are and because of that i wanted to make this video where we cover bitwise operators in detail we talk about how they work what they do and then we're also going to talk about where bitwise operators and how they're actually used and i don't want to say real life but in real programming now in order to understand bitwise operators we need to understand the binary system and bits in general and i'm not going to give you a full tutorial on the binary system here but we're going to go through a quick example for those of you who don't know about the binary system yet but i recommend you watch a detailed video on that now let's say we have a number 28. this number is a decimal number 28 and it can be represented in the binary system using zeros and once how is that done we basically look at powers of 2 and we ask the question of which powers of 2 28 consists of now 28 in this case consists of the next smallest power of 2 which is 16 then the next smallest power of two is eight so that would be 24 and then the next smallest is four this would be 28 and then we have not two and not one so we ignore them and this basically means one yes for sixteen one yes for eight one yes for four zero no for two and zero no for one let me give you another example if we have the number 19 for example that would be 16 not plus 8 because 16 plus 8 would already be too much so just 16 4 would also be too much because that would be 20 already and the next thing is 2. so 16 plus 2 is 18 and then plus 1 is 19 which means that this is going to be 1 because it's a yes for 16. zero zero because a no for eight and a no for four and then a one and a one because yes for two and one if that is too confusing to you because you think that i didn't explain it well or anything like that watch a video on the binary system that is how decimal numbers are represented in the binary system we have powers of two so the the bit on the right stands for one then we have two then we have 4 8 16 32 64 128 and so on uh into infinity or towards infinity and this is how numbers are represented in the binary system and this is what we're going to use in today's video in order to explain bitwise operators because bitwise operators as the name already suggests are operators that work with the individual bits of the binary representation so let's say we have a number one here uh first of all let me show you how you can look at the binary representation of numbers in python if we have number one equals 28 and number two equals 19 and as we had before what we can do is we can just say print bin off n1 and we can do the same thing here for n2 and if i run this here you will see down here we get the binary representation we get 0 b as a prefix and then we get 1 1 1 0 0 4 28 and then 1 0 0 1 1 for 19 as we saw now if i want to remove the 0b i can just say [Music] start from the second position like that and then we only get the binary digits here so let's just choose some random numbers let's go with uh 23 477 and 36 213 for example if i now represent these numbers in binary okay one is longer than the other so let's just make this a little bit smaller maybe 31 000 so that they have the same length those are now the two binary representations of these numbers and what we're going to do with those is we're going to apply bitwise operators and bitwise operators this basically means that we apply the logical functions which we already know hopefully at this point which are and or xor and so on to the individual bits so we don't have something like true and true or true and false we don't have booleans we apply these operators like and or xor and so on onto the individual bits and then we get a new number a new binary number as a result so if we have one and one this would result in one zero and zero this would result in zero one and one one zero and one zero so this is what bitwise operators are basically for we're going to start with a basic and and for this we're just gonna say number three is going to be n1 and n2 now we use a single and symbol now if you're coding in java or c or c plus or c sharp you know that if you want to use the equivalent to a python and which is a logical operator when we have something like true and false for example that is a logical operator if you do that in the other languages what you do is you use two and symbols here for the logical operator we use a single and symbol here so this means take the bits off number one and take the bits of number two and give me the result of the end function so i can go ahead and say print binary number three and there you go you can see here that this is the result of applying and to the individual bits one and one is one zero zero zero one one one zero and one zero one zero zero one one one for those of you who don't know what the end function is basically the and function is only one if both inputs are one or if there are multiple inputs if all inputs are one so basically one and one equals one everything else equals zero that's the basic idea of an and function again we're going to talk in the end about the use cases when do we need that when uh is this important we're going to talk about that for now we're just going to talk about the basic functionality if we want to use or or basically says that zero and zero is zero everything else is one so if at least one thing is one everything is one or the final result is one which basically means that n1 if i print let's say n4 is going to be n1 or n2 this is this pipe symbol here this is the logical uh the bitwise or so what we do now is we say print bin n4 what we get as a result here is we get let me just comment that out so it doesn't disturb us we can see that everywhere where i have at least one one i get a one as a result so here i have zero zero this is why i end up with zero but everywhere else here i have one or uh either two ones or at least one one um and we see one as a result here here we have two zeros again this is why we get zero and this is the basic or function again the or function always returns one if at least one element uh if at least one bit is set to one the final result is going to be one as well uh then we have x4 which is exclusive or the name already says what this does xor basically says i want to have one and zero or zero and one but i don't want to have two zeros or two ones it it has to be different it has to be either or or it's just or and xor is either or so i cannot have both it has to be one of them so one x or actually this is or this is not right uh one x or zero equals one and zero x or one is also one everything else results in zero which basically means that if the two values are different we're going to get a one so if i say n5 is going to be n1 and then we use this power symbol here this uh hat symbol n1 and n2 this does not mean n to the power of n2 that would be star star in this case this means xor so n1x or n2 is going to be n5 and we're going to say print bin n4 there you go so that's or actually n5 sorry when we run this let me just comment that out again [Music] you can see here that it has a leading zero that is not displayed because one and one is zero and if the number starts with zero it's not going to display that and because of that we're going to artificially add a zero just so we have the same length again uh they go so one and one is the same so zero zero and zero same zero one one is the same zero zero and one is different so a one one and zero is different so a one one one is the same zero and so on you get the idea of a basic xor then we also have a bitwise not or a negation operator the problem with this one is that it's not actually what you would think of as a bitwise knot which is turning all the bits around it doesn't work like that because we're working with unsigned integers which means that if you have an integer and you take the negation of that you're going to get a negative integer if it's positive obviously in the first place and the representation is not exactly just flipping the bits here and because of that uh this operator is not necessarily what we're going to use or what we want to use if we want to actually negate a bit mask because i'm going to show you here let me just comment this out and let me comment this out if i take uh n1 and i negate it with this wave symbol here this is the bitwise not or at least the negation operator here and i represent this in binary you're going to see that this first of all it's a negative number and uh second of all if i now remove the first three characters three because there's a negative symbol you can see that it's not actually the negation of the bit of the bits you can see here it is here it is but here we have the same bits i mean that is the same for both numbers even though i negated it so this is not actually a bitwise knot this is not actually inverting the individual bits and because of that we can do it ourselves so if i know for example that my number is going to have 16 bits or whatever amount of bits i can go ahead and say 0 b which is just an indication that i'm going to now write a binary number in python and then 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 16 once minus uh and then whatever number we have now first of all i don't know how many bits n1 has so we need to figure that out first before we do anything let's run this again uh 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15. so okay we need to remove one bit here and then we can say minus n1 let's print the binary result of that and remove the first two digits by doing that and of course we need to have a leading zero here by doing that we're going to get the exact uh negation we got one zero zero one one zero zero one one 1 0 0 1 and so on this is an actual negation now there are also other ways to do this but the ordinary wave operator which is the negation operator in python the bit wise not even though it's not really a bit wise not doesn't work like that because it works on signed integers it goes into positive and into the negative and it doesn't work like that then we also have shifting now shifting um is not like and or xor or not we're not applying it to the individual bits we're just shifting the whole number the whole bits to the left or to the right which equals basically in the decimal system um which is the same thing as dividing by 2 and multiplying by 2. so if i have shifts here and if i have a number let's say my number is uh i don't know 20 for example if i now say shift the number to the left one time so if i say shift equals 1 and then i print the number it's going to be 40. and i'm going to explain to you why that is if you don't know it yet because that basically means that we shift all the bits of the number let me show you the representation here so let's copy that and let's change this to binary and let's change this to binary as well you're going to see that what happens here is we're actually shifting the binary bits so instead of having 1 0 1 0 0 which is 20 we add a 0 a 0 to it because we shift it to the left and by shifting it to the left what happens is that a zero pops out in the end and this basically means that take everything times two so instead of having a one for sixteen we now have a one for thirty two instead of having a one 4 4 we now have a 1 for 8 and 32 plus 8 is 40. this is basically how it works now of course if i say number and then right shift equals 2 which means shift it to the right twice this will result in 10 and this is going to be uh basically just 8 and 2 so 1 0 1 0 and this is now going to be in binary representation so 1 0 1 0 as you can see this is 10. so shifting to the right and to the left is the same as multiplying and dividing by 2. so let us now get to the interesting part where are bitwise operators even used what can they be used for and chances are you have used bitwise operators in some context before without even noticing that you're using bitwise operators because it came intuitively or because you saw in a documentation that you have to write something like that but you didn't really think about what's happening behind the scenes and this is especially true if you're not only coding in python but in a language like c for example because what we oftentimes use bitwise operators for are so called flags so flags basically for example for permissions let's say we have the following system we have a permission set and we can set a permission for a user is the user allowed to read is the user allowed to write is the user allowed to execute or is the user allowed to change the policy now if the user is allowed to do all these things the bits are going to be one one one one because yes yes yes yes now if the user is only allowed to read and nothing else it's going to be one zero zero zero because yes for read and no for everything else this is a very basic system that we can use now let's say just in a fictional scenario here i have person one and this person shall have certain permissions the permission shall be this person is allowed to read but not to write not to execute and not to change the policy then person two is going to have the permission to read write execute but not change the policies now maybe i have some sort of system maybe i have a function let's say i want to do something with those two persons together and i want to check if they are permitted to do something so let's say together one is going to be the result of the permissions now let's say for this system i want to say you are only allowed to do it if all of you guys have the permission and this can be true for many more persons so people we don't have to have two people only we can also have five or six and they all have their permissions now if i want to say all of you have to have the certain permission then i'm going to use a bitwise and because in total i want to have the least permission or the the least powerful person i want to have here so if i have for example here person three four five and then i have this person that's allowed to do everything this person is not allowed to write but it can execute and read and this person is allowed to uh read write execute or read write and change the policy only whatever uh those are the permissions here and now i want to know okay what is the thing that every one of those can do so what is the least common perm or the least permission that they all have in common the least powerful permission that they all have in common what i can do for that is i can say person one and person two and person three and person four and person five this is going to give me the end the the bitwise end of all these permissions and i'm going to get the least powerful permission that they all have in common so if i print binary off together one i'm going to get as a result one zero zero zero because that person has the least permissions and every one of them can read this is what every one of them can do now if this person here for example is not allowed to read the least common uh or the least permission that they have is nothing because yes this guy can read but nothing else and this guy can write and change the policy but he cannot read and because of that if you want to see if you want to have the permission that they all have in common what can every one of those people do it's nothing because there's nothing that everyone can do this is what you can use an and for and then the other way around you can also of course say in order to be allowed to do that at least one of them has to have the permission so we can say for example for some task for some activity there has to be one supervisor that has all the permissions and then they can do whatever they want but one guy has to have the permission at least and then we can say together two is just going to be person one or person two person two or person three or person four or person five and then of course if i have um all sorts of weak permissions here so this guy is not allowed to do anything and this guy is only allowed to read as well and this guy can do two things but this last guy for example can do everything then the whole group can do everything so if i print together two everyone can do everything so this is one thing that we can do with bitwise operators and oftentimes this is probably something that you have encountered in code already you're going to have a certain flag constant so for example let's say i have a system and i want to have the flag neural reads the permission to read we still have the same system neural read would be 0 b 1 0 0 0. this is the permission to read this is only the permission to read now neural write would be 0 b zero one zero zero zero so only the flag uh or just two zeros only the flag for this particular permission is going to be set to one and i can do this for um execution as well so neural exec and neural change and i'm going to say 0 0 1 0 and 0 0 0 1 there you go now often times what we're going to do in c is when we have some i don't know some shared memory or some semaphore or something that we want to set certain flags for certain permissions for what we do is we set a uh we choose these flags and we use a bitwise board to combine them because if i want to say for example let's say def my function and i pass a permission to that function then let's say the function just prints that permission so it's just going to say bin and permission like that what i can do is i can say okay my function and the permission are i'm allowed to write and i'm also allowed to read for example come on read that is what i'm allowed to do now this is an or but it's actually an and in the practical content uh or in the practical context this basically means that i'm allowed to write and to read and if i run this you're going to see that this prints one one zero zero which is the permission for writing and reading and this is not something that i just make up here this is actually how it works in a lot of libraries in a lot of frameworks where you pass these permissions you use the bitwise or to combine them into one full permission and then you can use that to check if someone is allowed to do something using xor and using and and using or and so on this is what we can do now another interesting thing that we can do with the bitwise xor operators we can swap the values of two variables without needing a placeholder so let's say we have a equals 10 b equals 20. now of course in python we can do a b equals ba so that's not a big deal and then c we can do swap and all that but if for whatever reason you decide to do it with bitwise operators you can do it without a placeholder um because usually what you do is if you don't have a fancy function or a fancy notation like that you say c equals a then a equals b and then b equals c because of course you need to have some value that stores a temporarily then a is b and then b takes what a was in the first place now we can do it with bitwise operators without needing a placeholder and it works like that a x or equals b so we save into a the result of ax or b then b xor equals a and a x or equals b again now this might be confusing but if i now print a and then i print b you're going to see that we get 20 and 10 even though we started with 10 and 20. the variables are swapped now let me explain how this works if we look at the binary representation of 10 we're going to see that it's one zero one zero because it's one for eight zero for four one for two zero for one that's ten now we're going to add a leading zero because for the next one we're going to need five positions because 20 is 16 plus four so 16 yes eight no four yes two no one no those are the two binary representations of this number of these numbers what we do now when we take a x or b and this is true for all numbers is we get a binary number that has a 1 in all the positions where a is different from b from a binary perspective so it is different in this place so zero and one equals one one and zero equals one zero and one equals one 1 and 0 equals 1 0 0 equals 0. so we now have these four ones which indicate that at this position this position this position and this position a and b were different in the beginning if i now take that that binary number and i export it with 20 again what i get is i get a why do i get a because if i now take this here x or this i'm going to get the same as the original because i'm taking the number 20 and i x or it with this number and this number has once in all the positions where um were the numbers differed in the first place and whenever i take something x or 1 it's going to be the opposite 0 x or 1 equals 1 1 x or 1 equals 0. so it's going to invert the positions here and because of that what i'm going to end up with here is 0 1 0 1 0 which is a now if i now go ahead and say a is whatever i have an a x or b i do the same thing because now i have a stored in b and i still have this number here representing all the positions where a was different from b and i now apply it to the original value of a and it's going to give me b automatically because a xor with all the positions that were different from a and b will result in b so this means that i will get 1 0 1 0 0 there you go and this is why this works with a simple xor operation now last but not least we can also use bitwise operators to check whether a number is even or odd so let's say we have some number here and this is just something and all i have to do in order to see if this number is uh even is i have to say if some number and one results in zero then the number is even [Music] and otherwise it's odd so if i run this you can see that it's odd if i change this to eight you're going to see that it's even why is this the case because i have some number with zeros and ones here whatever it is and then i use the and operation on that a bunch of zeros and one which means that all of this is going to be irrelevant all we wanna know is if this here is one or not and if one and zero is zero then it's going to be even if it's one in the end it's going to be odd so we're just looking at the last bit basically and besides that also what i want to mention is that in a lot of algorithms that are uh recursive uh not recursive what was it uh in logarithmic time what we do often times would divide by two and in order to do that oftentimes we don't say x equals x divided by two but we just say x is shifted to the right by one so this is also something that you will see a couple of times in algorithms so that's it for today's video hope you enjoyed hope you'll learn something if so let me know by hitting the like button leaving a comment in the comment section down below and of course don't forget to subscribe to this channel and hit the notification bell to not miss a single future video for free other than that thank you so much for watching see you next video and bye [Music] you
Info
Channel: NeuralNine
Views: 3,531
Rating: 4.9834023 out of 5
Keywords: python bitwise operators, bitwise operator, bitwise operators, python operators, where are bitwise operators used, what are bitwise operators, bitwise operators application fields
Id: i1wQOiljBvY
Channel Id: undefined
Length: 28min 33sec (1713 seconds)
Published: Sat Sep 25 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.