 In the last segment we looked at how to translate manual algorithms into programs. We ran one program and in this segment we are going to see how we might recover if you make some mistake in writing the program. So here is an example. So this is the same program from last time except that these two statements. So this statement and this statement their order has been exchanged. So in the real program this statement came later and this statement came earlier. So we have exchanged it, exchanged the order. So first of all this is a bad program. It will not give the correct answer and let us see that. So here is the program in which the value of the statements has been exchanged. So I have called it ebuggy.cpp. So let us compile that program. So it compiles fine. So now let us run it. So let us try our test case 0. So this seems to run fine. Let us try our test case 1. Oh this also seems to run fine. So maybe well let us see. Let us try our test case 2. So here there is a mistake. We were expecting a value 2.5 but we have got the value 3. So how do you recover? Well there are 3 possible courses of action that you can take and you really should learn all 3 because once in a while one will be more useful than the other. Sort of the simplest thing to do is to put print statements to see whether not just the final value but whether the intermediate values are correct. What I mean by that is you put print statements. The program will print out the intermediate values and then you go over the intermediate values and you check are these the values that I was expecting or is something wrong. Another possibility is not to put print statements but do the same thing yourself. So you pretend that you are the computer, you walk over the program and on the side keep writing what values different variables are and at the same time keep on reasoning are these the values you expect to see and if not then you have found a mistake. The last way is to do the same thing but in a symbolic manner. So rather than saying variable capital T has the value 1 we are going to say what if the variable capital T has the value 1 over i factorial and we are going to symbolically try and reason out and see if everything is correct. So what do I mean then I say I put print statements. Well this last this red line. So we should remember that look at it is usually convenient to put print statements at the beginning of the loop. So that is because our plan has also been made for the beginning of the loop. So we can look at the values that get printed and we can look at the plan and we can see whether everything is fine. So our plan contains variables capital I, T and S so those are the variables that we are going to print. So let us again see this in action. So I have put in the statements in a program called edbug. So this here is the line where the print statements are there. So let us now compile and execute this, compiled and let us say run. We know that this program makes a mistake for the value 2. So let us see what happens over there. So if we print 2 we are going to see the intermediate values during the iterations. So here are the intermediate values. So the first time around when I was 1, T was 1, S was 1. This is as we expect. This is the very first iteration and in fact at this point the variables just have the values that we gave to them. In the next iteration when capital I is 2 we expect the term to be the previous term that got added and that was 1 over 1 factorial. So in fact it is 1. So this is perfectly good. Then we expect capital S the sum at the beginning of the second iteration to have the value 1 over 0 factorial plus terms until we get the term 1 over 2 minus 1 factorial or 1 over 1 factorial. So there are just 2 terms 1 over 0 factorial and 1 over 1 factorial. So the value is going to be 2 which is also what we have expected. So this means that there really was no error as far as the values were concerned in our variables until the beginning of iteration 2. So let us just go back to the program. So we have discovered that this value is printed correctly and the values printed over here are correct and therefore something must be wrong over here in this statement because until now S was correct at this point S was wrong so something is wrong over here. So if this statement is wrong then we are pretty close to the mistake and then all that we need to check is are we adding the right thing over here. So here we are adding 1 whereas we expect to add 1 over 2 factorial to this not 1 over 1 factorial and therefore we can see that this is definitely wrong and now we can realize that look this statement should come before this and then everything will be fine. So we discovered what the error was and by the way errors are called bugs in computer parallel sometimes and so we have figured out what the bug is and this is also saying that we have debugged the program. Another way of debugging the program is through manual program tracing. So here is our same program and now we are going to pretend that we are a computer and we are going to execute it, execute the program and keep track of what values the different variables have. So to facilitate this it is often recommended that you make a table. So you have a column for every variable. So let us not keep a column for N because N is going to be fixed once and for all and it is not going to change. So let us keep a column for I, let us keep a column for T, let us keep a column for S. So when we execute the first statement which is this here, then these variables get the value 1, 1, 1. Then when we go to repeat N, so let us say iteration 1 what happens during that iteration 1. So first we are going to change S to S plus T. So as a result we are going to get the value 2 over here. After that we are going to do T equals T upon I. So T equals T upon I, so we will get the value 1 over here. And then we will have I equal to I plus 1, so we will get the value 2 over here. Then we are going to go to iteration 2. So in this way we continue and we will realize that at some point the values that we have over here are different from the values that we expect. So again at that point we proceed in the way we did in the print statement case. So once we do that we will again figure out that oh here is the mistake and then we can remove it. Now many experienced programmers prefer doing this manually rather than putting print statements because somehow it feels that as you do this you are getting to know your program better and sometimes the print statements sort of are too confusing, there are too many things that happen at once and yeah so it really depends on your temperament but you should definitely consider this. Then the last and by no means the least important method is symbolic tracing. So again it is the same program and we are now the question that we are going to ask is let us assume that things have worked out until this point. Well we can check whether they have worked out at the first iteration. So how do we check that? We look at I equals 1, T equals 1, S equals 1. So that in fact has worked out according to plan because I, T and S have exactly the values recommended over here. Now we are going to check symbolically whether we did the right thing that is whether our updates are in fact doing what we want them to do. So what is this update doing? It is taking the old value of S and adding it to the value T. So we are going to, we are assuming that the T value is this, the S value is this. So now if we add this value to this value what happens, oh something wrong. The last term over here was 1 over I minus 1 factorial and we are adding 1 over I minus 1 factorial to it where we, when we should have added 1 over I factorial. So clearly we have made a mistake and again if you think a little you will realize that oh we really should have divided first so this statement should come first. So let me conclude. So first I want to say that you must write down specifications clearly. In this particular program things were quite simple but if you take a real life problem the experience is that in many programming projects there are delays and people go, people write wrong code because they did not understand what was required of them. They did not understand what the specification was. So please take the time to make sure that you are understanding clearly what is expected of you. Then you should construct test cases because first of all they are useful when the program is ready but because they also are an indication that you are actually understanding what is expected of you. For much of this course it will be sufficient for you to write a program that mimics what you do by hand or what you do manually. For this you have to be quite conscious, you have to be very, very intimately knowing what exactly you do manually. So think about what you do and think about what structure it has. So for example you may ask when I am doing solving this problem I am doing these phases which look very similar. So you might ask how many phases because that is going to tell you that oh I should use a repeat loop and it should have so many iterations. You should also state in general terms what each phrase accomplishes. So in terms of that phrase number so you should say something like phase number. In phase I I am going to take the term calculated in phase I minus 1 and whatever. So it had better be general because generality is what helps you write programs. And yeah so as I said phases become iterations of the repeat statement and you can, you should note that you may want to number the phases so you can number them conveniently. In our case we started with fun but there may be other situations where you may want to start with 0. And you should determine what you need at the end of the phase or at the beginning of the phase. So the end and beginning are really very similar because the end of phase I is the beginning of phase I plus 1. So in any case you need to know what it is that you need to remember at that point and those the things that you need to remember will need variables. So the structure that we had in this program is actually very common. So what is that structure? You have a set of variables and you want them to assume specific values at the beginning of iteration I where I is anything, I could be anything. For all possible values of I you know what values they need to take. So this knowledge should be put in the code in form of comments. And this knowledge what is desired, what values are desired is often called the invariant for the loop. So for all loop iterations this statement has to be true and therefore it is called an invariant. You can ensure that the invariant is true for the first iteration by initializing variables correctly before you enter the loop. Now for the subsequent iterations you can assume that the invariant is correct at the beginning and then you should change the values of the variable so that it becomes correct at the end. So that is what the code in each iteration is supposed to be doing. And to get this right it is good to be careful, it is good to ask look I want the value of this variable to be divided by this variable. Now it could be the value at the beginning, the value at the end, which value am I supposed to use. So be very careful about that and then it will make sure that your statements, your updates will happen in the right order. If you write a program and it does not work correctly you should not give up hope, you can make sure that it runs, you can attempt to remove the bug, the error. So for this you can put print statements to check if the variables have the values you expect in each iteration. You can trace or manually execute your code or you can symbolically execute your code. Now I am going to leave you with an exercise and this is again the same series that you are supposed to calculate except the plan or the invariant given to you is slightly different over here. So the invariant is stated in those comments and you are required to complete the initialization and the loop steps and make the program work correctly. So this is the end of this lecture sequence and I will strongly urge you to try the other exercises given at the end of chapter 4 which is the reading for this lecture sequence. Thank you.