 Good morning everybody and welcome to the lecture on arrays. What we will discuss here is the structure which denotes the set of values or a set of variables in our C programming language which is what we call arrays. We will look at how the array elements are accessed and how elements are manipulated or how computations are done. We will also analyze the quiz from previous lecture because there was a query raised again for a slightly elaborate explanation on what I call the code optimization by the compiler. The correct technical name for that is loop invariant code and I will spend about 10 minutes describing that particular explanation. Before introducing arrays we will revisit an example which we had considered earlier. You will recall that we had written a program to find out the largest of three values. Then we had also extended that program to find out the largest of five values. I have written a variation here which finds out the largest of four values. At that time we had remarked that it would be extremely difficult to extend this kind of programming to find out the maximum of say 100 values. So more specifically we had noticed that we have situations where we will require to handle multiple values of similar kind. So all the values v1, v2, v3, v4 they were either integer or floating point or whatever and there would be similar other situations where we will be required to handle multiple values and we obviously cannot define and use different variable names for each of these values if they are either too large in number or the number of numbers is unknown. So I have indicated here two reasons why I cannot do that easily. Firstly it is inconvenient v1, v2, v3, v4 how many names I will write and how many names I will handle in my program. My program will become unwieldily long. Second it is impossible if we do not know how many variables which we have to deal with. Additionally we may wish to manipulate matrices. We have numerical computational problems where we have to solve simultaneous differential equations or even simultaneous algebraic equations. How do we for example add multiply find inverse of a matrix? So matrix operations which is kernel to most of the scientific and engineering computations currently we do not seem to have any mechanism to handle such amount or such kind of data. So we clearly needed different mechanism than just simple variables and we mentioned to our students that yes we have such a mechanism and it is called arrays. We introduce the notion of an arrays by saying that if we want to have a one dimensional array containing some n numbers let us say maximum 100 integer values I want to store in that array then my representation of the array on paper would be something like this. What I would like to now say is that if I have 1, 2, 3, 4, 5 elements then I would like to refer to these 5 elements as first element of an array, second element of an array, third element of an array etc. Currently the mechanism that we seem to have is to name different variables to represent different values even if we say a1, a2, a3, a4, a5 this 1, 2, 3, 4, 5 is incidental in the variable notation because when our Dumbo matches or maps them onto the computer memory all that it does is it will have a different name for this location, different name for this location, this location etc. In this fashion I might have a 100 as the name for the 100th location. So essentially this is not the way the memory mapping should be done and that is why most of the computer programming languages including C programming language introduces a notion whereby such group of values can be given a single name and accessing individual element of that set is permitted to be done through some kind of an indexing function. So let us look at how the array is defined and how array elements are accessed. Each element in the array behaves like any other variable but is referred to by the array name and an index. So we have to tell our students that when we write a opening bracket, 0 closing bracket this is not same as the name a0. This is rather 0th element of a set of values which collectively are represented by the name a. Similarly a5 will mean 6th element, ai will mean ith element or i minus 1th element etc. Why am I saying 0th, 1st, 2nd etc. That is because C or C plus plus and this is continued, this practice is continued in many modern programming languages. The array index begin with 0. So that means the 1st element is always called the 0th element and not 1st. If we have to show the memory mapping of such a definition of an array then we consider the same array that we had 53, 79, 41, 94, 38. We will now say 53 is the 0th element, 79 is the 1st element, 41 is the 2nd element, 38 is the 4th element. And we will now show the memory mapping where we will indicate that a opening bracket, 0 closing bracket is not really a name. The name is only a but this 0, 1, 2, 3, 4, 5 etc. represent the index values which will be associated with that particular set. In terms of writing things in our program we explain to our students that an array is a special data structure. We emphasize that it is actually a set of values and we state that values must be of the same kind. So it is important for our students to understand imperatively that you cannot have an array where one element is integer, another is a floating point value, third is something else etc. All values in an array must be of the same type. The way array is declared is very simple. Just like we declare a variable int x or float y or whatever we can say int a in bracket 100. This declares an array a with 100 elements and causes our compiler to allocate 100 consecutive memory locations in the memory collectively referred to as a. Each individual memory location is capable of containing an integer value and successive memory locations can be accessed by using an index to a. I have given another example of a name. This is deliberate. Please note the difference between the first and the second. It says float daily temperature values 31. What is it that I am trying to indicate? I am trying to indicate that the name of an array or name of a variable could be much longer than what we have been using. This is a dilemma by the way all of us face as teachers. In order to shorten the material on our transparencies or even to reduce time wasted in writing things on the board, we tend to use smaller names for our variables. In actual practice, in professional programming it is not permitted simply. Why because as you know very large programs have to be written by teams of people and a program written by one person may have to be read and modified by some other person. Consequently there are coding rules which are explicitly followed in most of the professional programming and among others. One of the early rules in that coding standard states that the variable names must be meaningful and therefore if a name is chosen which is an understandable acronym for something it is not considered a good practice. In fact it is considered a very bad practice. The implication is that we as teachers are often unable to convey to our students by examples that the names should be longer and meaningful. Since we will have to continue to use simpler names because of the restrictions that I mentioned namely we want to save time and we do not want our transparencies to be cluttered only with long names because our idea there is to emphasize the logic in our program. Consequently there are two methods by which we can communicate this important aspect to our students. One is once in a while keep coming back to the examples like this where you show that variable names or array names should be meaningful. They are need not necessarily be very long but they should be meaningful. Secondly in our lab exercise that we offer if we ever give sample programs it is preferable to have meaningful names in those programs. Let us continue our discussion. We now tell our students that the name of the array represents the entire set of values and thus cannot itself alone be used directly in any computation. So it is totally wrong for example for us to say something is equal to a multiplied by 5. In the context of a simple procedural programming language like C such a statement would not make any sense because a is not a single value but is rather a set of value. And even if we wanted to say multiply every element by 5 there is no way we can say a multiplied by 5. We have to individually access different elements of the array and do whatever operations we wish to do on that. So we mentioned that any element of the array can be used wherever a variable can be used. So not the name of the array but an element of the array and a reference to an array element is made by using an index. So how exactly a reference is made? Index can be any expression which will be evaluated first. A single value will result this value will be converted to integer if necessary. Although ordinarily we will always write integer expression involving integers there is no reason to have anything else. But there could be peculiar situations where an index expression actually comes out as a result of some floating point computations. The nearest equivalent integer will then be used as converted by C from that float to integer. So to repeat again an index can be any expression which will be evaluated first and the resulting integer value will be used to identify a particular element. Index for the first element is 0, second element is 1, etcetera, etcetera. Here are some examples A4 means the fifth element. Fifth in our natural counting by the way C will call it fourth element only because the first element for C is 0th element. But counting in our terms A4 will mean fifth element. A j where j is now an expression remember that. So even if I write a single variable name as far as C is concerned it is an expression consisting of a standalone variable. So A j for j equal to 86 means 85th element. A j minus 52 notice that this is an expression. So in this expression j minus 52 this will be first evaluated whenever we make a reference to A j minus 52 this expression will be evaluated. Let us say the value of j is 86. The resulting value of this expression will now be 34 and that will represent 35th element. I am sorry here there is a syntax error. If j is equal to 86 this should mean 87th element and not 86, 85th element. Index expression should not have any undefined value at the time of evaluation. A good question to ask is what will happen suppose I have said A j in some expression say y is equal to 3 plus A j minus something and at that time j has not been initialized to any value by us. Well what will happen is the computer will use whatever value is there in the location for j. If the value is 1000 it will take that value and try you will attempt to find out 1000th element or 1001th element of A whichever way you count. Since an array A has been declared only to have 100 elements 1000th element does not exist. It is a interesting question to ask to both ourselves and to ask our students what would the computer do in such a case. The correct answer by the way is that in the olden days when there was no memory protection either at the hardware level or even at the software level the machine would simply go to the sequentially 1000th location within the group where the memory has been allocated to the array. Now that element does not even belong to you it might be somebody else's program or it might be data belonging to your program declared somewhere else and it will merrily use that value for whatever computation. In case you assign a value to A j where j is undefined or j becomes 1000 or something some location in the memory will get assigned that value which is not naturally belonging to your array. Whether you have hardware or software protection needs to be examined by running the program. As far as c programming is concerned it simply says that results will be unpredictable if the index expression works out to a value which is outside the bound of array definition. The bounds for array definition are 0 to 99 in case I have declared an array with element 100 or size 100. So this needs to be kept in mind to recapitulate then an array is a set of variables of the same type reprinting the same type of value. Individual elements can be accessed by giving an index expression which could be a simple numerical integer value or it could be a complicated expression. Secondly the value of the index expression must evaluate to within the range of the defined elements. If I had defined an array to be size 100 then the index expression must work out between 0 and 99 otherwise an unpredictable error will result in the execution of our program. With this now we try to solve the problem that we started discussion with namely if we wanted to find the maximum of three numbers four numbers five numbers we were forced to write v 1, v 2, v 3, v 4 etcetera. Now we are equipped with the structure called array and this is an example of how the array can be used. So here I declare an array of integer numbers of size 100. I want to find out maximum so I declare a variable I do not know how many exact number of values I want to calculate the maximum of it could be 5, 10, 25, 30 it cannot obviously be more than 100. So n will be representing the number of numbers whose maximum I want to find out and then of course there is a variable I. Now you look at the program logic the program here after defining the variables and the array reads n as input and then for I equal to 0 to n minus 1 it reads a I please note that when I write a I it does not mean one variable but it what it means it depends upon I since I will be varied from 0 to n minus 1 in this iteration when this input statement is successively executed n times it will read the n values given from input and will store these values in successive locations of the array. So when I is equal to 0 it will read a 0 when I is equal to 1 it will read a 1 and so on. Look at the ease with which multiple values can be read and stored inside our memory without any problem a single iteration is adequate to read in all the values this kind of feature therefore is very convenient to handle. Look at the way we will find out the maximum now remember we had generalized the maximum finding algorithm by saying that we will first allocate the first number to maximum and then we will compare this maximum with successive other numbers if any new number is found to be more than maximum we replace the current value of maximum by that number notice that exactly the same logic is applied here since all the numbers have been read I know the first number which is a 0 I assign a 0 to max as a starting point next I set up an iteration which will now change I from 1 to n minus 1 notice that in our iterations which have to run n times we usually start with 1 and we say I less than equal to n k r has to be taken to ensure that the index I because I propose to use I in my index as a index expression the index I must start with 0 and must end with n minus 1 and that is the reason why this peculiar way while reading I say I equal to 0 to n minus 1 having taken care of the first value in my algorithm I want to compare max now with the second to n minus second to nth element so I start with I equal to 1 which represent the second you look at the logic here so you come back here so having started with one value for max I now say for I equal to 1 to n minus 1 I compare the value of max with the next element of the array if I th element of array a I is greater than max I simply reset max to a I this is the way I will go through this iteration examining successive elements of a so when I come out of this iteration at this point whatever is the value of max is obviously the largest value amongst all the elements I will just output that particular value saying maximum value is max and of course this is our backslash in for a new line so very simple and elegant implementation of finding out largest of n numbers and indeed we can now extend similar logic to handle any large number of numbers in any problem situation before revisiting the program for estimation of pi where I want to answer that question I also want to have some interaction let me mention I will I will show this example now we will be considering more examples using arrays later but this is one interesting example to which the reference was made when we discussed the data types I had mentioned that integer and long will permit you to represent integers with such and such precision smaller precision for in and a larger precision for long and there were some questions raise what if I want to represent a much larger number in fact I even got a couple of males that if I want to handle very large numbers what is the data type that I should use the answer to the last question is that there is no data type intrinsically available in C programming language or for that matter in most other programming languages that is because most programming languages are written to implement roughly the native capabilities of a computer for your programs and since native data types on computer hardware are integer and some life float and so on therefore the programming languages do not go beyond permitting you to use the kind of precision that is intrinsically available of course there are programming languages which will permit you to define precision and so on and if the underlying hardware does not support it they will implement it using some software but in general handling higher precision numbers is not a natural characteristic of any programming language but we know that in many scientific applications in many technical computations we will have to deal with much higher precision here I intend to show you that arrays can be used effectively to represent such numbers how can we do that firstly we can store individual digits of a number in successive array elements so suppose I want to store a 20 digit number ordinarily a single int or long etc will not suffice it will not hold that number will get an overflow but suppose artificially I will say that I will store these 20 digits into 20 locations of an array then if I say int special number say 100 and in the first 20 locations I store the 20 digits of this number well I have a representation can I add number stored in this fashion can I multiply them can I subtract one from the another in short can I do arithmetic operations of such numbers the answer is yes and no no you cannot use the conventional c programming operators like plus minus etc to do these computations yes because once you have represented values in your own fashion inside the computer program and since you can manipulate individual array elements exactly like you are manipulate variables it should be possible for you to write your own programs to do addition of high precision numbers subtraction of high precision numbers etc indeed there are software packages which very scientists use which implement such high precision arithmetic they are called high precision numerical computation library what our intention here is to show to our students that it is indeed possible by writing our own programs to handle arithmetic for high precision numbers so let us go to the example here first of all how do we represent the high precision numbers so let us say we arbitrarily decide as I just mentioned one way of reprinting this is that I put every number into an array now I will have different numbers some number may be seven digit long some number may be twenty three days long some number may be fifty four digit long if I store the number digits of the number directly how will I know what exactly is the length of that number please note that if I have a seven digit number twenty digit number in an array of hundred elements I store first twenty digits of that number directly that twenty first element of that array may contain some digit from the past in which case our own program later which it tries to manipulate this array will never be able to find out exactly how many digit number I had originally stored in that array consequently I have to think of some other strategy one strategy which I am suggesting this is not necessarily the best strategy but this is one strategy each one of you can come up with a different mechanism of storing such number the strategy which I am suggesting is I will use the first element that is the zero-eth element of that array to store the number of digits so if there is a twenty digit number num zero will store the value twenty having done that I will use the successive elements one two three four five etcetera to store actual individual digits now if we decide that this is an adequate representation well we can reprint two such high pressure numbers in arrays m and n let us say assume that a number has a maximum of ninety nine digits then if we declare arrays as m hundred and n hundred we are ready why do I say ninety nine only these have hundred elements remember we said that our representation and please note this is strictly artificial this is between you and me nobody else knows that our numbers are reprinted like that so it is the programmers this but having made this decision I know that even though I have two arrays of hundred elements each the first element namely the zero-eth element of m and n will be used to store the number of digits in that number and therefore the number of digit positions available to me to store actual number is only ninety nine but by ninety nine is as big as hundred if I want to store hundred digit numbers at most then I will have to declare the arrays as hundred and one you may now write a program to add these two numbers and store the result in third array here I have declared another array int r one zero one well my numbers are at most ninety nine digit long so why am I storing why am I declaring an array with hundred and one element for a ninety nine digit long number I need only hundred you can actually ask your students and most will be able to figure out that look if I add two numbers each of which is ninety nine digit then because of the carry that may happen if the numbers are very large the result will have one extra digit whether to retain that extra digit or whether to tell the user that look the result of your arithmetic operation is going beyond my capacity of representing ninety nine digit numbers because that is what a C compiler will tell you if you add two integers which are individually capable of being stored inside the computer's memory but when you add them the result goes beyond this there are two options one the compiler tell you there is an error the other it will discard the higher order digits or bits and whatever number remains it will show you incidentally this is the reason why many times you see negative numbers when you successfully keep adding values to an M and that is because a number goes beyond some point the most significant bits are simply discarded and if you have one as the most significant bit in that 32 bit number it represents a negative number so these interesting things can happen in real life with our C programs there is no reason why these interesting things could not happen with multiplication arithmetic packages that we write anyway to come back we have two arrays M and each can store a high precision number with 99 digits we have decided on our own peculiar way of representing these numbers the first element stores the number of digits in that number and subsequent elements store the successive digits first the input if we had to feed in large number there is no way that large number can be written as a single number if you write a large number 1 2 1 7 2 4 5 3 7 3 7 3 7 4 9 8 2 etc as a single value the company will get confused what will you read it in you can't read it in in anything other than a integer variable and that has maximum limit of seven digit it is possible for you to group these number into five digit groups etc and read individual into an integer variable but that is silly having decided on an array representation the best way for me to say is that first I will give the number of digits in a number and then I will supply individual digits as individual numbers very obviously then my input will be first a number four this will be followed by number nine five two one if the number I wish to represent is nine thousand five hundred and twenty one this is not a very large number this is only a sample please remember that even if I have a high precision capability it must be capable of storing smaller numbers as well in the same representation because otherwise I cannot operate upon those here is another six digit number nine nine six three five seven so the input will contain first a value six and then individual digits nine nine six three five seven so if I have the arrays m and n then I must read the input such that at the end of reading this data I should have m zero as four which is nothing but the number of digits in the first number and m one m two m three m four to have nine five two one which are the digits of this value similarly when I read the second number n zero should be six and n one n two n three n four n five and six should be nine nine six three five seven I hope this much is very crystal clear now I have got two high precision numbers read into the memory let us say I want to add these two numbers can I simply add m one to n one m two to n two n m three to n three etc etc notice that the way these numbers are written ignore four and six currently but if you just read this number this is nine five two one this number is ninety nine thousand six three five seven the way we have stored these two numbers in an array is that the first position of one array contains this first position of the corresponding second array contains this can I add the corresponding positions obviously not when I say that add this number forget this four and six just look at nine five two one and nine nine six three five seven if I add nine plus nine eighteen I do not even know what to do with carry if I add nine plus five four I do not know what to do in any case is wrong addition how do we add we do not add numbers like this we first align them on the right so the number nine five two one it will be seen that's a four digit number I will notice the larger number is a six digit number so I will align the smaller number to the right by putting zeros here artificial so my correct way of putting first number is zero zero nine five two one then the second number nine nine six three five seven now I can add this is common sense we all learn this in second third standard we know exactly how to do that but having stored the data in a peculiar way in the arrays we will actually have to do some jugglery to achieve the results like this we also note that whenever sum of two digits exceeds nine we have to add a carry to the next thing so seven plus one eight no carry five plus two seven no carry five plus three eight no carry nine plus six fifteen when you get fifteen you have to remember that fifteen is the value and if you do any arithmetic operation on variables you will get a value much greater than nine because variables are capable of handling large value but when you get any value larger than ten you have to realize that in the corresponding result location you cannot store fifteen so you have to break it up you have to find out a modulo ten remainder which is five because five is the digit which will go into the result and now the quotient that is one will have to be taken as a carry so consequently for the next position when you add this you can just add nine and zero you have to say nine plus zero plus carry one that will become ten again you will break that ten into one and zero zero will remain here one will go as a carry nine plus zero plus one is ten this time you will put zero here again you have a carry since there is nothing else left in the next higher digit position you store this one notice that this is the reason why the resultant array R may occasionally have an extra digit such a digit will always be one if I am performing a addition operation or later on as we shall see a subtraction operation of negative numbers or an addition operation of two negative numbers could also result in a carry notice that currently we are not dealing with negative numbers at all that is some extension that you may have to think of as some kind of homocyte so again to recapitulate I do not add numbers in the way I store them I have to realign these and after realign I have to add them using the rules of addition where I have to have a carry I now wonder suppose I have shifted these numbers let us say I use some artificial additional arrays instead of m and an R I say m dash n dash and R dash so m dash and n dash m dash and n dash will have the same values as m and n but they will all be right shifted so that I can start adding from the last element onwards what do I do about the logic of addition I can't write a separate logic for digits which generate a carry and a separate logic for digits which don't generate a carry so let me generalize any particular addition whenever I add these two numbers let us say this is the ith element of m dash and this is the ith element of n n dash m and n are the two arrays that are my normal logic of the addition will be add m i to n i and add to it a carry what is the carry here it is 0 but that is incident if I think of logic where every time I do addition of two digits I will always add those two digits and also a carry for cases where carry is irrelevant I will set carry to 0 but wherever a carry comes out from a previous operation I will set it to 1 this way I get a generalized instruction which can be iterated around I have tried to show this logic in some segment of the program here max digits is equal to m 0 greater than n 0 m 0 colon n 0 what is this Greek and Latin I shall explain this slightly in a in a second this is to find out which of the two numbers has larger number of digits and what is that number in the example case that we have given one is a four digit number other is a six digit number when I compare m 0 to n 0 I will find out that m 0 is not greater than n 0 m 0 is 4 n 0 is 6 since it is not greater the value of this question mark expression will be the second option the colon distinguishes between the two options so this will be n 0 which is 6 now consequently max digits will be assigned value 6 had the first digit been the first number been larger let us say 13 digit then 13 would have been greater than 6 and then this expression would be evaluated to take out the first value which is m 0 I have tried to explain this through a side comment here max digits equal to m 0 greater than n 0 question mark m 0 colon n 0 actually means the following statement if ordinarily I may write this if m 0 greater than n 0 max digits is equal to m 0 else max digits is equal to m 0 as a matter of fact most of us who do not know this particular kind of statement usage would write this if you ask me I would prefer the way to write to be this what this does is it is very concise and for those people who use this question mark operator very often this is natural please note that this it is called a question mark operator by the notice this question mark here that is the operator here on the left of question mark there is a condition on the right of question mark there are two expressions separated by a colon what the question mark operator does is it evaluates the condition on the left hand side m 0 greater than n 0 this condition may be true or it may be false if the condition is true then the first option given before the colon is evaluated which is an expression and the result of that expression becomes the value of this entire expression if the condition is false then the computer evaluates the expression written on the right hand side of the colon symbol and it results into some value and that value become the value of the expression so m 0 is the first expression in its entirety and n 0 is the second expression in its entirety because in this particular case m 0 and n 0 respectively contain the number of digits of the two numbers which is what we want to find but in practice this could be any complicated expression and in short the meaning of this particular usage of question mark operator is to calculate a value and assign it to max digits as per this logic so this whole statement is exactly same as if we had stated if m 0 is greater than n 0 max digits is m 0 else max digits is n 0 now I know the max digits I am presuming in this program segment I have not shown how to rearrange your numbers in m n n arrays into m dash and n dash I leave it to you you can think of how to shift because you see you have you have all the digits at the beginning your first element the most significant digit next element second and so on so if you have 17 digit number and 32 digit number that is how you have stored them realignment means you have to shift all of them on the right most side of the array m dash and n dash respective resuming that you have done that let us go to the previous slide resuming that you have done that the m dash and n dash arrays will now contain this in their higher order elements so if m dash is 100 n dash is 100 then m dash 99 and n dash 99 will contain the last digit of my number similarly m dash 98 and n dash 90 will contain the second last digit and so on and because I am assuming that we have already done this shifting the smaller of the two numbers would have been padded with zeros and of course the first element of m dash and the first element of or other 0th element of m dash and 0th element of n dash will continue to contain the total number of digits in each of these that is why we are making that comparison here of course we are I think comparing with m 0 directly it does not matter in fact the first digit of m dash and n dash does not really matter at this juncture but we will retain the similarity there anyway now let us look at the actual logic of addition it is indeed very simple very cute but we may have to understand what we are trying to do I will go back to the previous slide to show that what we are going to do is exactly this add two digits in a corresponding position along with a carry so my addition r dash i will always be m dash i plus n dash i plus carry the value of the carry could be 0 or 1 as is appropriate when I begin my addition iteration because I am going to do it iteratively first this element then this element then this element etcetera etcetera notice that I can set up this iteration because I am not dealing with hundreds of variables names I am dealing with exactly elements of just two arrays and the index expression for each of these arrays is controllable by me and is best controlled by a for loop so that is exactly what we propose to deploy here so this is the logic having found out what is the number of max digits I will run an iteration from 99 up to 99 minus max digits plus 1 consider this in the present example the largest number is 6 digit number so value of max digits is 6 consequently which are the positions I have to add 99th because that is the last digit 98th 97th 96th 95th and 94th I have to add 94th 99 minus 6 will be 93 93 plus 1 will be 94 consequently this iteration will run from 99 to 94 one at a time reducing I every time because I am going from right most left words so first the last element then the last but one element then the last but one element and so on this is what sets up the iteration please note that before starting with the iteration I am setting carry to 0 because the first time it is 0 definitely now I start within the iteration what do I do m dash I plus n dash I plus carry m dash I plus n dash I plus carry is now resulting value I assign it artificially to r dash I plus 1 you may wonder why I am doing that I will examine that I plus 1 location is it greater than 9 what would it signify if the resulting value is greater than 9 then I have got a carry so that means psi 7 plus 1 12 12 is greater than 9 5 plus 4 9 no carry but whenever it is greater than 9 I will have to recalculate carry and I will also have to recalculate the correct value which shall remain inside the final result location if r dash I plus 1 is the final result location which currently contains let us dwell I have to find out module or 10 to decide that only two will remain here and carry will become one any time the result is greater than 9 that is what I am doing I am going to do it repeatedly again and again and again here this except that I might have set carry to 1 in some let us say fifth digit but after the sixth digit is added there is no carry so somebody has to set carry to 0 again I do not forget to do that so I check if the result was greater than 9 then and only then the carry should be 1 otherwise the carry should be 0 consequently I will keep on doing this with the correct value of carry and at the end I will get the correct result I had a choice between discussing only this example throughout the class or discussing something else and relegating this to a later period of time what I have decided therefore is that I have included in your lab docket a complete program which adds to high precision numbers and one of the lab assignments today says please go and study that program and the assignment says now modify that program to subtract to do subtraction the program does addition so happy high precisioning for your lab today let me go back to the other example which I wanted to give now I start the discussion so please regard this to be continuation or beginning of the discussion now we still have about 20 minutes and we will have some interaction some additional questions may come but to begin with I would like to revisit the issue where yesterday we saw that in one of the ways when we were estimating the value of pi we had written an algorithm and the original program had instructions which had n into n we had noticed that this is the instruction which will do maximum amount of computing because this is multiplying i with i j with j n with n so three integer multiplications and this whole statement is executed in the innermost loop this loop runs for n times this loop runs for n time so consequently this complicated operation will be carried out n square times so I am going to do three multiplications in square time and we were wondering whether we could reduce that this is where we have said that we could do this segment that since n is not changing within the loop body this multiplication can be done only once outside the loop and the result can be stored in a variable and then used in our expression in the loop this is what we had done so we are modified our program like this we had written these iterations but before that we calculated n into n and assign it to a simple variable n 2 then what we did is that inside the iteration wherever n square was to be computed I simply substituted this n 2 consequently when we run this program we expect that earlier I was doing three multiplications now I am doing only two multiplications of course I am doing a comparison etcetera whatever but three multiplications instead of that I am doing two multiplications since this statement was being executed in square time I would have expected that this is the major computation there is no hardly any other computation I would expect roughly one third reduction in my execution time and yet yesterday we saw that when we ran this version of the program with the time command the computer did not show any appreciable reduction this is where we started speculating and I had put up that case one of the options in that case which incidentally turned out to be the correct answer is that look we have cleverly noticed this and done this but the very first program that we gave this one when we gave this to the compiler the compiler was also equally clever the compiler also noticed that in this program you are doing nothing to reassign the value to n so the value of n remains what it was before this there is no change and if there is no change why should I calculate n into n every time in the iteration why I cannot do these computations outside in short exactly as we thought this also thought the compiler also thought like that and it did something equivalent to this it created a temporary variable of its own calculated n square separately not calculated but generated instructions to calculate n square once just before the loop assign it to this temporary variable and then use this temporary variable in the instructions which is generated to translate this particular state it is true that modern compilers are capable of doing this kind of optimization of the code and this particular technique is called loop invariant code promotion or code movement so this is roughly inverse what I just discussed in the quiz we are looking for reasons why no saving is there and one of the possible reasons was that perhaps the C compiler had figured out this situation and had done exactly the same thing you know where I found the best and concise explanation for this phenomena not in a book on compilers I was tempted to do that but I knew that the compiler will describe this simple concept in about ten pages the best example I found and the best explanation I found in Wikipedia I will once again request all colleague participants to try and ensure that you read Wikipedia to find out about some particular term at least once a day believe me it is the modern book of knowledge and it has amazingly useful contents on technical and scientific aspects now the topic that we are discussing is not simple technical description of a normal thing it is actually a feature of advanced compilers and yet it is described so well let us just quickly look at this description those of you who have studied computer science or teach courses like compilers would appreciate this very easily for others I would just like to say that compiler is nothing but a program a system software program written by someone which actually reads our program written in lines of text converts it into machine language instructions and then those instructions are ultimately executed by the machine originally the compilers used to be mechanical they would just translate take this instruction and write equivalent instructions now the compilers actually try to capture the semantics or the meaning of our statements by analyzing in depth the program that we give and they can figure out such things so here is the description that Wikipedia gives in computer programming loop invariant code consists of statements or expressions in an imperative programming language which can be moved outside the body of a loop without affecting the semantics of the program. So, loop invariant code means the execution of the code can be done outside the loop without causing any difference to the actual semantics or meaning of what we have in the loop. So, look at n square since n was not getting redefined at all inside the loop in fact it is this feature is called reachable definition. So, that means the point where the value of n is defined is not inside the loop but it is outside it inside the loop the value of n is not being redefined in all such cases such code can be moved and it is called loop invariant code motion this is a compiler optimization which performs this movement automatically. For example, if all reaching definitions of the operands of some simple expression are outside of the loop then the expression itself can be moved out of the loop now at this juncture not all my colleague participants would be in a position to understand what is reaching definition and so on. So, let me just continue with the simple example that Wikipedia gives but the example that you have seen you would have understood what we are trying to do but there we are doing it manually here is an example Wikipedia gives of a computer program consider this program for i equal to 0 i less than n plus plus i x is equal to y plus z i th element of a is equal to 6 into i plus x into x. Now, what the compiler does is it analyzes this code it finds out that x is being redefined. So, any computation where x is involved cannot in its entirety be moved out of the loop because x is being defined in every iteration but it notices that in this iteration is changing. So, 6 i would be different itself is defined in terms of y and z and y and z are not being redefined in the iteration. So, if there was some value of y and z earlier say 5 and 6 then x would remain 11 here whenever you compute even if you compute it million times x will every time be only 11 consequently this line of code itself can be shifted out of the loop once this is shifted out everything involving purely x can be shifted out x square appears in this expression but this 6 into i depends on the loop variable i. So, only x square can be moved out consequently it identifies such segment of the code and it moves it out of the loop this is called the loop invariant code x is equal to y plus z is a loop invariant. So, let us see what the modern compiler does our GCC by the way does exactly this that is why if you run that program for pi estimation you would not find any difference. So, in this particular case what the optimizer will do now what the compiler will do compiler will now imagine that x is equal to y plus z was to be calculated outside. So, it will actually move that instruction up then it will introduce a temporary variable t 1 and it will calculate x into x exactly like we are calculating n square we are calling it n 2 and now it will rewrite the code automatically within the iteration saying a i is equal to 6 star i plus t 1 that is the reason why even though I might have written a program using the previous code, but how it will execute will be this I hope this is a satisfactory explanation. So, I would like to have some interaction with the participants. Sir my question is what is the maximum size we can allocate for float array. Thank you when you talk of size of the array by size we mean the number of elements in an array firstly there is no limitation that the compiler puts on describing the size of the array by size I mean the number of elements. So, let us say you have an array x as I said you could have 100 elements 5000 elements, 20,000 elements, 1 million elements. So, what is the practical limit if there is no limit imposed by the compiler itself first of all the size will have to be put in as a number by the maximum number that you can write which can be understood by the compiler is the largest integer value it can represent. So, clearly the size of any array cannot be prescribed by you cannot be defined by you as a number which itself is greater than the limit of the integer representation. However, I must add very quickly that that number itself could be very large and you may not have actual physical memory containing those many locations. So, in principle the conclusion is there is no limit on the size of an array at least there is no compiler imposed limit generally. However, there would be a practical limit which will depend upon the actual physical memory that you have. I want to ask a question regarding if how do you sort just of n numbers n can be infinity without using any sorting technique over to you sir. This appears to be a philosophical question to me than a computing question the question is how do you sort n numbers where n is infinity I am not aware of being any human being being able to input infinite values into a computer the values will not end, but his or her life will end much before that. Can you rephrase your question kindly let me answer this question your questions actually has some discrepancies you are saying how will I sort the numbers without using any sorting technique that is an impossible question whatever I do to sort that itself will be a sorting technique. So, please remember that such questions are ill framed questions secondly n cannot be n can be any number in actual practice but when you write a program you have to define a maximum value of n because it is that maximum value up to which the numbers will have to be stored internally when you sort them whether you store those numbers inside the computer memory or whether you store them on the desk. The sorting techniques that we are discussing are called in memory sorting techniques and in memory sorting techniques usually will work on some maximum array size which will hold all the numbers. So, imagine that you have a limited physical memory and you have implemented a sorting technique which will sort let us say 1 million numbers at a time which is the maximum number when you define maximum to be 1 million your n can be half million 10,000,5 whatever it is as long as it is less than 1 million. Now, consider that you have a disk space in which you have a billion numbers using the sorting technique that we ever discuss in the class which is of the in memory type billion numbers cannot be sorted if the computer's memory is inadequate to hold those billion numbers. So, consequently there are other sorting techniques which are disk sorting techniques those sorting techniques what they do is even if you have a very large file containing very large number of numbers it will keep taking portions of those numbers sort them in segments and will do what is known as a merge sort. Theoretically there is absolutely no limit to the number of numbers that you can sort using merge sort. It will only limit on the capacity it is limited by the capacity of the disk that you have and the amount of computing time you have. But please note that in the context of teaching programming such questions are extremely ill framed. So, I would suggest that you tell your students to consider practical limits of the size of memory and the size of disk and since we do not discuss disk sort in the first course in programming it is better to tell our students that when we discuss sorting using disk files then we will get this answer as to what is the larger and larger limit up to which you can go. As far as our courses are concerned the first course is concerned we should say that the number of numbers that I can sort will be limited upon the total memory capacity and of course this sorting technique that I will use. Thank you a person from Jalandhar has asked a question again related to the efficiency of the algorithms. His question is that yesterday I pointed out that you would first like to try to reduce the order of complexity of the algorithm and if I have the algorithm of the same order then I would like to reduce the what you call parameters or the coefficients of that expression. His actual question is that since these coefficients will depend upon the computer hardware or the computer system that you have in which way you can reduce them. I think let me put that question in proper perspective. I have a particular algorithm. I cannot reduce the coefficients directly by manipulating them. Yes the coefficients depend upon the particular hardware that you have. So if your computer takes so many nanoseconds or microseconds for addition it will continue to do that. What I meant is that I will rewrite statements in my algorithm such that I do less number of arithmetic, less number of multiplications, less number of additions by moving my instructions around. When I do that automatically the number of comparisons, number of multiplications I do in my algorithm will reduce and thereby the coefficient will change. So please note that the coefficient is not dependent entirely on your machine. What is dependent on the machine is the unit time for executing individual instruction. What is dependent on us is how many of those types of execution we do, how many multiplications, how many additions etcetera. So I am talking about rewriting my algorithm such that I reduce those operations and that is what will result in the reduction in the coefficient of the equation. I will repeat the question for benefit of all. What is the top down approach in a language? I would like to first correct the question. The approach that you are talking about is actually a program design approach and it has nothing to do with a programming language. You may use any programming language. The approach that you talk about is feedback. So to answer this question the top down approach actually talks about the way we approach the design and writing of our software. It is not related to a programming language. So even if you are programming in Pascal or programming in Java or programming in any programming language, top down approach is about the style in which you design your programs. Since we cannot go into great details at this juncture because this is not a course in software engineering but we will merely say that modular well designed programs need to be written by us and top down approach is actually a way to look at a problem holistically first, broadly classify the problem into components and then look at individual components in greater details. So the top is the entity of the problem having broken down into let us say three sub-problems or three sub-areas. You identify each one and work out the details. So when I write a program I must holistically first thing. Consider this approach of reprinting and handling addition of two high-prison numbers. High-prison numbers are not even represented in a program. So what is the top level thinking that we did? Let us artificially represent these numbers in arrays. So that was the top level thinking. The next level thinking is what would be the detailed representation? Then we said one approach is you put the number of digits in first location and the actual digits in subsequent location. Now having done that now we are saying we want to add these numbers. So how do we add the top level thinking was first? I understand how the numbers are added and therefore I decide that I will have to realign the given numbers on the right shifted. The next lower level thinking then is to write code to do that shifting. How do I add? I generalize the addition by saying I add any two digits with a carry and the carry can be either zero or one. This is my top level thinking. This implementation you saw in terms of that code. This is very crudely I can explain the notion of top-down approach. I repeat that this approach is more related to the way in which you design and write programs and has absolutely nothing to do with the programming language. So whether it is C or C++ or Java or SQL or whatever it is you will have to follow that. I am being reminded that we have to stop this session. I assure you that we will continue this discussion in the second session.