 In this lesson, we're going to begin learning about numerical systems that are different than the decimal system that you're most likely used to using. Let's talk a little bit about why we might actually need to learn these new number systems. Looking back in history, we can look at George Boul, who in about the mid-1850s or so, mid-1800s, had a couple publications that really formalized this idea of logic that we're still used to today. And it wasn't too far later and on in time, or in a bit late 1800s, that a colleague, Charles Pierce, described how these logical operations of true and false that George Boul laid out could be carried out by electrical switching circuits and electricity at the time is still fairly new. This digital or on-off, one-zero, true-false or Boolean system is the building block upon which all modern computers were built. These first electronic digital computers were developed around the end of World War II, which is where our earlier lessons in this course have left off with those electrical or electromechanical machines. These early computers were about the size of a large room and consumed as much power as your modern computers, in fact several hundred modern computers. And it was around 1937 when Claude Shannon was at MIT and his master's thesis implemented these Boolean algebra systems, or binary arithmetic, using only electronic relays and switches for the very first time in history. And it was at this point that purely electronic circuit elements would be starting to replace their mechanical and electromechanical equivalents in many areas, most notably for our purposes, cryptography. At their core, computers really just run by processing binary, as we mentioned on or off, one and zero information. That are run through wires or circuits or signals through those wires. Knowing how to work with those binary representations or binary numbers, and actually other numerical base systems as well, are going to be key to our understanding how modern computers can implement cryptography algorithms. In this course, we'll focus learning binary, or base two numbers, or of course decimal, or base ten system, and we'll also learn hexadecimal, as these are the three numerical systems that are most commonly used in computing. So when we talk about positional number systems, what we're really talking about is the base of the number. When we talk about the base, the base is a number that identifies the value of each position in the number, and how many different characters or numerals are needed to represent a digit. So for example, as modern humans, we typically use a base ten number system, perhaps because we have ten fingers or we have ten toes, and each numeral in that number represents some count of how many powers of a certain power of a ten there are. So for example, the number 127 or 127, the fact that the one is on the far left means that the one there would be different than say a one on the far right of that number. The one on the far left or in the third position means that that number has one grouping of 100 in there. The two means we've got two groups of 10 included, and the seven mean we've got seven groups of one included for a total of 127. But there are other base systems that could have been used for counting. So besides our base ten, which uses the numerals zero through nine, you can have a base eight system, which is called octal, and it only uses the digits zero, one, two, three, four, five, six, and seven. You can have a base 16 number system, which is called hexadecimal. It uses the numerals zero through nine, just like our decimal system, but then also has the characters a through f to represent the next numbers after that. And then our base two number system, which we'll focus on today, mostly, which is binary, which only uses the numerals zero and one. So let's dig in a little bit and see how these are used. Let's just get a quick refresher again on our base ten number system. To say we have the number 4237. Each one of these positions in the number means something slightly different. The four means there's four of ten to the third powers. There's two ten squareds. There's three ten to the first and seven ten to the zero. So the total value of this number, we'll use some color coding here to keep track of it, could be computed by doing four times ten to the third, plus two times ten squared, plus three times ten to the one, plus seven times ten to the zero. And we call again, we call this a base ten number system because ten is the base of each of these factors in the terms where it's ten cubed. Ten is the base of that exponential part. Ten squared, ten is the base there, and so on. We'll remember this pattern when we start working with other bases besides ten. Now, you might be wondering, how could I tell if a number is a base ten number, or a base two, or a base 16, or whatever? Base ten is typically the standard anywhere you see a number. If there's no other visual indicators, you may safely assume that the number we're talking about is base ten. An octal number could have a subscript at the end, like 21 with a subscript of eight, or in the computer, will have a leading zero and then the lower case letter O for octal, and then two one. Hexadecimal, likewise, could have a subscript of 16 at the end of the number, or in the computer, it could be the leading zero with an X, X for hexadecimal, and then one one. And then binary could have a subscript of two at the end, or in the computer, we'll see uses zero with a lower case B, and then one zero zero zero one, all your binary digits after that. So here we have kind of an old fashioned car odometer system to kind of show how we can count in these various number systems. So you can see in the top row, we've got binary, and that one's digit just keeps alternating zero to one, and then it flips over the next digit, and then that goes zero to one, and it flips over the next digit, and so on, and so on, and so on. Decimal, the second row, you probably are familiar with. We can see those digits go all the way from zero up to nine, and then we've completed our positional counting in that space, and it flips over the one in the 10 spot. And then that would keep going until we got the decimal value of 100, where the next one spot would flip over. The third row, we have hexadecimal, start counting at zero, and then we count up to the letter F, when it flips over the one to the two there, like we just saw in the hexadecimal. It'll go from zero to F again, and then flip over the two to a three. The octal system, we can see counts just from zero up until seven, and then it flips over the next one to a one, zero to seven again, and then flips the one to a two, and so on. And the last row is just kind of a custom system. I don't know what you would call a base 36 number system besides just a base 36 number system. It's important to remember that every one of these rows on this image here represent the same exact decimal value that we can see counting at the bottom, value 43, 44, 45, and so on. They're just different ways to represent the same number. We'd call all of them the same thing, seven, eight, nine, ten. We just write them out differently. Now some things to point out. A binary number will always need the most number of digits to represent this number because it has the fewest number of digits that it could use in any one position, so we're going to need the most kind of number of positions to represent it out total. The bigger your base gets, like base 36, you're going to need fewer positions to represent that number because you have more choices as a number in each one of the positions that you actually use. So you're going to be counting longer in each position before you have to start using the next position to the left. If you want to play around with this, there's a link here in the next slides and I definitely recommend you take a look at it, play around it, and get a good feel for these different ways of representing the same values. Let's get some practice here, converting from a binary number to a decimal number. Here we have on the screen 101.1 and I don't really know what to call this number besides 101.1 because I don't have a good decimal representation. The language that we have developed to describe numbers is inherently based off of the decimal system. So we're going to need to convert 101.1 into a decimal number. If I want to tell you its value using the English language that we know and love. So we're going to, again, color code this number to help us keep track of the different component parts. And that one on the far left means we have one grouping of two cubed and we'll add to that zero two squared groups plus one two to the first group and one two to the zero group. So that's one times eight plus zero times four plus one times two plus one times one for a total of 11 in a base 10 system. We can do the same thing with hexadecimal. Here we have the number 2B7E, no idea what this is, but let's go ahead and convert to decimal. So we have an idea on how to explain this or denote its value verbally. So we'll have two times 16 cubed plus 11 times 16 squared. B is equivalent to 11 in a decimal system. It goes 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, and so on. So B is 11. And then we'll have 7 times 16 to the first power. And then plus 14, E is the same thing as 14, times 16 to the zero power. Throw that all into a calculator of some sort and you get 11,125 in our base 10 system. Now, we can do all this paper, pencil, or handheld calculator, but it might be good to know how to do this in Python as well, so we can implement this into our computer code that we've been writing. Now, again, I've mentioned this before on the odometer image, but it's worth mentioning again, we're always talking about the same number. We're just looking at different ways of representing that number, decimal, octal, binary, whatever. It's the same number. It just looks different. We're writing it differently. So we could do this in Python by just asking the computer to print out and then we can type it 0B to denote binary 100001, that's 17. So we had one in the 16 digit, the 16 spot, zero in the eight spot, zero on the four spot, zero on the two spot, one in the one spot. It's for a total of 17. I could have asked Python to print 0X11 because a one in the 16 position and a one in the one position, that's 17. Or I could have just asked it to print the number 17 written in decimal. If you don't specify the number type, Python will assume that you mean decimal because as humans, we usually use decimal. And you can do all of your same mathematical operations, additions, subtraction, multiplication, division, you name it. You can do those with these different number types because at the end of the day, Python's going to convert them all to the format it needs to do the operation, likely decimal behind the scenes, but maybe binary at some point as well. So Python will convert all of these to the number type that it needs in order to get the job done. Now, suppose we had to go the other way. Say we have a decimal number and I want to convert that to a binary number. So I've got the number 42 here. The strategy that's usually easiest for us to use as humans is think about the power of two. That is the biggest number, but that is less than the decimal number itself. So in this case, 42, I want the power of two that's less than 42, the biggest one of those was not two to the zero. That's one is not two to the one that's two, but it is two to the fifth. That's 32. So 32 is the biggest power of two. That's still less than the number we're trying to convert. So I'm going to put a one in the two to the fifth power column here or position, and I'm going to go to the next one, two to the fourth. Let's see, if I were to add on 16, which is two to the fourth, that would give me 52. That's too big, which means I can't actually have a one in the two to the fourth spot. So I'm going to put a zero there and get rid of that plus 16. Let's go to the two to the third power. Let's see, two to the third is eight. Now we're going to add eight on to the 32. That would bring me to 40. 40 is still less than 42. So I'm going to put a one in that spot. I'm going to need that number there. We'll go to the next one. Let's see, can I add a four? That would put me at 44 too big. So I can't have a four as part of the sum. So I can't have a one in the two squared spot. So we're going to put a zero, get rid of that plus four. Can I add a plus two? Yes, and in fact, that would get me exactly where I need. I'm going to put a one in the two to the one spot. This total here is, in fact, 42. So I know I don't need a one in the two to the zero. And I've now converted 42 to a binary number. One zero, one zero, one zero. We do the same idea with hexadecimal. So it's a little bit harder to do. You got to know your powers of 16. The biggest power of 16 that we can utilize to, as part of our sum here, that's still less than 541 is 216 squared. 16 squared is 256. So twice that is 512. So we need 216 squared. That's still less than 541. I'll have to add on, I think, one power of 16. If I added on two powers of 16, I'd be larger than 541. So just one power of 16, that brings me up to 528. And now that means I need 13 more. So I only got my one spots left. So I'm going to need 13 in the one spot. And 13 in hexadecimal is the letter D. So to convert 541 to hexadecimal, it become 21D. Again, it's still the number 541, but to write it in this positional system, hexadecimal base 1621D. Now, probably shouldn't surprise you that we can do this in Python as well. We can convert from decimal to another base. Python will always, however, the way that we do it, convert that number to a string in order to display the representation. Remember, Python default, when it's showing you a number, will always show you the decimal unless you ask otherwise. So we're going to use the format function to help us do this. You can give that format function a decimal number as its first argument, so 42. And you give it a string that represents the base of the number you want it converted to as the second argument. So we're going to print out what we get back from format 42 comma B, and we get 101010. We saw that in our earlier example. We can do the same thing with hexadecimal. We can convert 42 to hex by providing the x string as the second argument to the format function. So 42 as hexadecimal is 2A. Now, remember, both of those are strings. Format returns a string. So the output of the format function you could not use with other mathematical calculations because it's not actually a number anymore. It's just showing you the characters in the right spots that would represent that number. Now, if we have a string that represents a binary or a hexadecimal number, and we wanted to convert that back to an actual integer that we could work with, you could use the integer function. The integer function in Python allows a string in the first argument. So here's our string 101010 and the base in the second argument. So this will convert that string that represents a binary number to an actual number we could work with as long as we provide the correct base. We can do the same thing with hexadecimal. So we have to provide the base of 16 as the second argument to the int function. So that int function will return back an integer or a number that you can use for future calculation work. And that's it. That's positional number systems to get us started, what they are, how to convert, and how to use Python to do all of those steps. In a future lesson, we'll talk about some actual operations that are unique to some of these numerical systems. And then we'll get into how do we actually use these to start encrypting messages.