 In the previous segment, we said that the notion of problem solving and algorithms is quite old and it predates computers and that human beings have been solving numerical problems and using really sophisticated algorithms for a long, long time. We said that an algorithm can contain operations which are precisely specified. They could be arithmetic operations, there can be conditional operations and there may be that some operation sequences have to be repeated and it is important for you to remember throughout this course that you really know algorithms, you have learnt algorithms throughout your schooling and what we want to do is simply translate them into programs, translate what you know into these stylized syntax of a programming language. So in this segment, I want to talk about how a computer works or how a computer solves numerical problems. So here is a quick outline of this segment. I am going to talk about circuits. In particular, I am going to talk about something called digital circuits. Then I will talk about how numbers are represented in circuits and then I will describe at a very high level the parts of a computer. Then I will talk about a machine language program and what this process called compilation that we have alluded to means. Okay, so let us begin with digital circuits. Digital circuits are really the building blocks of computers. So a digital circuit is simply a circuit in which we human beings interpret the voltages and currents as numbers. So there are some voltages and there are some currents and we are going to interpret those as numbers. So here is a way in which we interpret. Here is the simplest convention. So we may say that in a particular circuit, in a particular wire really, if the voltage goes above 1 volt then we will think of it as the number 1. If it stays close to 0 then we will think of it as the number 0. Now digital circuits are typically designed so that voltages will never be between this 0.2 and 1. So we will always be able to interpret a voltage as a number in a very unambiguous manner. So from now on I might say something like the voltage is a 0 or the voltage represents the number 0 or there is the number 1 on this wire or there is the number 0 on this wire and that really should be thought of as that there is a voltage of 1 volt or higher than 1 volt on this wire or there is a voltage of roughly 0 volts on this wire. We might also talk about currents. We might say that current smaller than some value represents 0, larger than some value represents 1 and we might say that the charge stored on a capacitor also denotes number. So low charge may mean number 0, high charge may mean number 1. These are just conventions. Whatever conventions we use we have to stick through with them entirely. Now note that capacitors are particularly interesting because once we store a charge on a capacitor it can stay there unless we connect the two endpoints of the capacitors. So if the charge is stored because it can stay there a capacitor is typically used as a memory element. Now I have told you how to represent zeros and ones but once you know how to represent zeros and ones you will see that you can represent anything really and we will see this in a minute. Now the point of all of this is that V and by that I mean electrical engineers. Electrical engineers can design circuits which perform arithmetic in the following sense. So they can design a circuit such that if you feed a set of voltages to that circuit which represents a certain set of numbers then the circuit outputs the voltages that come out of the circuit will be precisely the numbers which represent the sum of those numbers, sum of the numbers fed on the input. So such circuits can be designed. It requires ingenuity but people can do this. Not only sums you can design circuits which perform multiplication so they compute products or they perform quotients they can perform square roots essentially whatever you want. So that is the reason why circuits work so beautifully for computation. So we know how to represent zeros and ones. So now I am going to tell you how to represent non-negative numbers. Basically the idea is we are going to use many capacitors or many wires to store or represent a single number. So the typical numbers of wires or capacitors that we use are 8, 16, 32, 64 maybe even 128 and bigger numbers maybe 96, 128 something like that. So how does it exactly work? So suppose I want to store 25 using 32 capacitors or 32 wires or in abstract terms we can say using 32 bits. How do we do that? Well we are going to first convert 25 to binary. So what is 25 in binary? It is this last thing at the end 11001 so that is 25 in binary but we are going to use it using 32 bits. So we are going to have a total of 32 binary digits or bits over here but of course the more significant bits are going to be all zeros. So this is the representation of 25 using the binary system so that is the first step that we are going to do and if you want to store this value in a computer then we are going to store a charge pattern where h represents high or the number 1 and l represents low or the number 0. So we will have 32 capacitors and they will have the following pattern of charge is stored. So this capacitor will have low charge, low charge, low charge and essentially that will mean that the number 0 is stored on this capacitor, this capacitor, this capacitor whereas some capacitors will have high charge representing the number 1. Again 2 low charges high charge. So this is how we will store 25 in our computer using 32 capacitors or if we are going to send that data from one part of the computer to another part we will use a pattern of currents or maybe a pattern of voltages of this kind low, high depending upon whether the bit value in binary is 0 or 1. Now if we are restricting ourselves to using 32 bits how large numbers can we store? Well we can have the pattern consisting of all zeros. So all these numbers, all these bits are 0 then that will represent the number 0 or we can have all these numbers be ones. So that is going to be the largest number in binary and in decimal that number is 2 to the power 32 minus 1. So any number between 0 to 2 to the power 32 minus 1 can be represented using 32 bits or 32 capacitors or 32 wires. This is not a small number, this is something like about 10 digits. So you can if you want a larger number than that if for some reason you need those numbers then maybe you can use 64 bits or maybe even more bits. Now if you want to transmit numbers then you have to send higher low voltages on as many wires that is all that is needed. So I have been talking about binary representation but here is a quick revision of binary representation really is what binary representation is. So binary number is a sequence of bits or binary digits. So binary digit is 0 or 1. So I might have a digit a bit a n minus 1 a n minus 2 a 1 a 0 and so on and in fact there is a point there which now we should probably call a binary point and then the digits following that I have numbered minus 1 minus 2 minus k. In fact the subscript indicates the significance of that digit. As an example I might have a binary number 101.11. So what is the decimal equivalent of it? The decimal value simply is whatever that digit is multiplied by 2 to the power this same i. So for here that 0 will be used and this will be 2 raised to 0 so it will be a 1 but in other places whatever the other things are used. So what is the value of 101.11? Well we just have to do exactly what I said. So this 1 is a 0 1 2 a 2 so I am going to have 1 times 2 to the power 2. This 0 is a 1 so I am going to have 0 times 2 to the power 1. This 1 will have value 1 times 2 to the power 0. This value have this 1 will have value 1 times 2 to the power 1 minus 1 and 2 to the power minus 2. So this number is really 5.75. So in this way if you give me a binary number I can convert it into a decimal number. I can convert decimal integers V to binary and here you may know that if I divide V by 2 the remainder gives me a 0. And I can repeat the previous step with the quotient that I get when I divide by 2. So the previous quotient I take and if I divide it again then that will give me a 1. If I divide it one more time then the remainder will give me a 2 and so on. Converting fraction F to binary is sort of natural. So for example you may note that if this fraction F is bigger than 0.5 then the first binary digit or the first bit after the binary point this will have to be 1. If it is then you can throw that you can subtract that value. For example there are many ways to do this and if what remains is bigger than 1 fourth then this next bit will also be 1 otherwise it will be 0 and so on. So this is just a very quick way a quick introduction or a quick revision of binary representation. You really do not need to know carefully what happens to fractions but at least I am sure you know how to deal with integers binary integers and this is just a quick revision of that. So going back to representing numbers so we talked about how positive integers can be represented but suppose you want to represent negative numbers negative integers how do you do that? Basically the idea is so one sort of idea is that one of the bits can be used to indicate a sign. So let us say the sign bit equal to 0 means a positive number equal to 1 means a negative number. So if I want to store minus 25 I am going to do exactly what I had earlier so this is the representation of 25 but the most significant bit that the first bit in this entire number I am going to make it a 1. So this does not mean 2 to the any longer it does not mean 2 to the power 31 it means minus 1. So this is just a matter of convention now. So we have to decide some convention and we have to stick to it. So if our convention is that the first bit designates the sign rather than being the part of the number in that case this sequence of bits is going to represent minus 25. So here we are saying that the left most bit is a sign bit but once we do that we know now that the largest number is going to be a 0 followed by all ones. So this is going to be at most 2 raised to 31 minus 1. So the range has reduced a little bit. So this is going to be our largest positive number. So I can have the negative numbers also so if I put in a 1 over here then that becomes a negative number so that number now goes to so it starts with minus 2 to the 31 whole thing minus 1 it should be 2 to the 31 minus 1. The actual representation that computers use is not exactly like this. It is something called 2's complement. So we are not going to discuss that and these specific details are really not important but you should know roughly what happens so that you at least have a good idea of what is reasonable and what is not reasonable. So we will see why we are going through all this. So in our very first lecture you wrote this statement in insights. So when your program executes I am going to tell you what is going to happen. So C++ will typically designate some 32 capacitors in your computer for storing the variable insights. So later on when you talk about insights the computer will refer to these specific capacitors and the value stored in these capacitors. The bit pattern that gets stored the low high charges that get stored or the 0, 1 values that get stored on each charge will be interpreted as a positive or a negative value. So say the first charge or the first 1 or 0 will decide whether the number is negative or positive and the rest of it will decide what the magnitude of it is. So that is how the representation works. You get some 32 capacitors and depending upon how you decided once and for all how the numbers are going to be stored the pattern of bits stored in those capacitors will be interpreted according to the convention you fixed. Now C++ actually allows you to write the statement unsigned insights as well. So in this case you will get 32 capacitors but now you are telling the computer that look I am never going to store a negative number in this variable. So please interpret the entire 32 bits as the magnitude of the number that I stored. So in this case if you store the number 1 followed by all of these things it will really mean 2 raised to 31 what this bit position represents plus 25. Whereas if you have stored this pattern in a variable which is just declared int then it would be interpreted as minus 25. So how you declare how you define that variable what type variable you say it is will tell you will tell the computer how to interpret those interpret the value of the bit pattern stored in that variable or stored in those capacitors. Now the terms bits bytes half words words are also used I should just mention them once a bit is 1 binary digit. So in other words just one number and it can only be a 0 or a 1 byte is 8 bits half word is 16 bits word is 32 bits and the double word is 64 bits. One byte of memory really means a memory capable of storing 8 bits or typically it means 8 capacitors. Of course there are ways of representing or remembering numbers without capacitors in which case it will mean some other kind of devices maybe 8 other kinds of devices but it is safe to think of memory as being capacitors for the most part. How do you represent real numbers because after all we deal we need to deal with real numbers temperatures humidity all these things are real numbers not integers. Here we are going to use the analog of scientific notation. So what is the scientific notation? We write a real number as a part called a significant times 10 raised to an exponent. So for example Avogadro's number is 6.022 into 10 raised to 23. So we are going to use exactly this on a computer as well but the significant and the exponent are in binary and so the number is going to be interpreted as significant times 2 raised to the exponent. Instead of 10 raised to exponent it is 2 raised to exponent that is all that is the only difference. So the question is how many bits do you allocate for the significant and the exponent? So this representation scheme called single precision says that in my representation scheme I am going to store the significant using 24 bits and the exponent using 8 bits. So one important point is that when we are storing floating point numbers it really is in two parts. So there is a significant part and then there is the exponent part and you may further note that the significant also might have a sign and the exponent might also have a sign. So each of these things really are also in two parts. Now why are we choosing these numbers for single precision? Well turns out that these numbers are sort of good, they have been found to be good in practice and one other reason is that 24 plus 8 is 32 which is one word. So a single precision real number or a single precision floating point number as it is called fits in one word. So I should also say that 24 bits of significance can really represent precision of 7 or 8 decimal digits. Then there is also something called double precision. So here you are not going to use one word but two words. So you will have 53 bits, you will dedicate 53 bits to store the significant and 11 bits to store the exponent. So you will have a bigger range in the exponents as well as more precision in the significant. So it is like scientific notation, how many digits are you going to write in the significant? The more digits you write the more precise, the more accurate your representation is and whether you are going to allow exponents to be larger is simply going to say well is your, how big numbers can you store? So it is exactly the same when it comes to binary as well. So a double precision number will fit in a double word and you should know that 53 bits of the significant are equivalent to 16, 17 decimal digits. So that is really a huge amount of precision. So I do not think anybody really will require more precision than that but if they do there are ways to get it. The actual representation for single precision and double precision is more complex and it has more features as well and it is the so called IEEE floating point standard which your computers implement and with the C++ language also implements. So just a very quick, indicative example. So just to make these things more real I am going to tell you how we might represent Avogadro's number. This is not exactly how Avogadro's number is represented on your computer but this is indicative of how it might be represented. So first we convert it to binary. So it might be this, 6.02 might be this and 10 raise to 23 might be that. So that number might be 2 raise to so many. So now we are going to represent the significant using 23 bits of fraction and 1 bit for the sign of the fraction. So 24 bits totally and 7 bits for the magnitude of the exponent and 1 bit for the sign of the exponent. So 2 raise to 1 0 0 1 1 1 1 0 so that is what I have replicated over here and I have put a sign bit and this pattern I have stored over here and what I get over here is this pattern. So there is a 0 and so these are positive numbers and that is what this is. So the decimal point is assumed after the second bit so there is assumed to be a decimal point over here. So this is what it is. These black bits, what are these black bits? Well they are bits which were not there but we needed 24 bits of significant and so these bits are just padded up as 0 bits. Notice that this representation is inherently imprecise and the fraction is only represented to a certain finite number of bits. And in fact this is not really a property of the binary system even in the decimal system, even in the standard scientific notation this problem is there. So nothing new really. And as again I will point out that the actual representation is really more complex. So this is not IEEE floating point, this is just something similar to IEEE floating point which I have given over here just to tell you what it might look like or so the actual thing is more complex. So one quick thing for you to think about. So suppose I want to represent 8 digit telephone numbers. So which representation should I use? So should I use an 8 bit representation, 16 bit representation, 32 bit representation or a 64 bit representation? And should I use unsigned or signed? So you are expected to fill in the blanks over here. So what you are supposed to do is not use too many bits because you are using memory unnecessarily but not use too few bits either because if you use too few bits then that number will not fit there. Then these are just questions for you to check whether you are paying attention which is bigger by your half word or what is roughly the largest number that can be represented using 64 bits. And I want the answer in decimal. So here you might want to note that 2 raised to 10 is 1024 which is about 10 raised to 3. So this way you can calculate what 2 raised to 64 is very easily at least approximately. So what have we discussed in this segment? We have discussed that numbers are represented by sequence of zeros and ones. And we have discussed that the same sequence may mean one number as an unsigned integer, a different number as a signed integer and a third number as a floating point, interpreted as a floating point number, a single whatever, single variable position floating point number. Now it is important to note that the capacitors only store high or low charges. They are not aware in any sense that the charge represent the numbers. So we have to keep track. So when we write a program, we designate a memory location as having a variable as having type int. So that is when we are telling the computer that look, look, please remember that what is stored in this has to be interpreted as a signed integer or if we call the type unsigned int as an unsigned integer. And there are ways to specify the types so that the computer interprets it as a 32 bit floating point number or a 64 bit floating point number. So it is our responsibility to remember what type of number we are storing. And if we remember it consistently, then there will be no problem. I should also point out that please do not be scared. You really do not need to know binary number system. So whatever you type has to be in decimal and C plus plus will convert it to binary. So you do not have to type binary, do not get scared. And C plus plus will also do the other thing. It will convert binary numbers that it has on the computer and print out decimal numbers. So both ways it will do it. So you can only think about decimal, the familiar decimal number system. But then why are we teaching you this? We are teaching you this because you need to know roughly what is going on. You need to know that whatever you are storing has finite precision and how many digits of precision you are getting roughly. So if you are going to want to think about how much error is my calculation containing, this discussion will be important for you. So you should know roughly what range of numbers and how precisely the numbers can be stored in different formats. So that concludes this segment. We will take a break.