 Today we will continue with a bit more study of assignment expressions and after that we will move on to managing control flow between statements starting with if then else and then the switch statement. So we will repeat a little bit of material from basic assignment so that if anything is unclear you should raise questions and then we will look at a couple of new kinds of assignment statements. So a typical simple statement in C++ will compute the value of an expression as the right hand side and then assign that value to a variable on the left hand side. For now because we have only seen basic variable types like in float character the left hand side always has to be a variable name you cannot assign to a constant you cannot assign to an expression that does not make sense. When later on we start looking at arrays very soon and then somewhat later more complicated data structures like two dimensional matrices or queues or lists or trees then the left hand side can look far more complicated but for now the left hand side should be a simple variable name then that is the kind of statements you have seen all along so far. Now these numeric types that we have studied and then the character types they can be combined into various arithmetic and Boolean expressions we have seen that already. For example to swap two numbers you declare a temporary you assign it to one of them and then do the switch then there are these more complicated arithmetic expressions and we have seen that expressions are built out of operators. Operators are like plus minus star slash multiply and divide and the way you write down the expression decides the order in which evaluation happens. There is an implicit precedence between operators as specified by the language manual and there is a link in the web in the course website to the C++ standard manual. So you can look up the respective precedences of operators how tightly do operators bind to the operands or the arguments which are being passed to them. So if you say the second expression 5 times Fahrenheit minus 32 over 9 without brackets that would lead to the middle expression tree. If you want it to be the correct conversion from Fahrenheit to centigrade that is the first expression you have to write it down as the first line and that will translate to a completely different expression evaluation tree. So inside the compiler when you write down an expression the first job the compiler does is to scan that string you have typed and turn it into this kind of an expression evaluation tree. After that the leaf nodes are either constants or their variable names. These variables are fetched from memory into registers or constants are loaded into registers and then information flows from the leaf of the tree upward toward the root ok. So as evaluation happens intermediate nodes and edges carry values and eventually the root value is the value of the entire expression fine. So that is the rule of evaluating expression and then finally when the expression is evaluated it can then be assigned to the left hand side variable. The third expression and its corresponding tree gives you one of the roots of a quadratic equation some of you will cover in this year this week's lab. There are also logical operations which you build up by inserting relational operators between numeric types or integer types or character types. For example you can test if 5 is less than 13 which evaluates to true or you can test if 10 to the power 5 is greater than or equal to 2 into power 6 which is false. If you want to test for equality that is 2 equals instead of 1 which is an assignment or you can also test for inequality by saying not equal to. Now one of the things you need to be careful about is when you are comparing floating point numbers test for equality and test for inequality are tricky you need to do the right thing depending on the situation. We will see one example of that today. Each such expression a logical expression is either true or false. So when I said that C++ supports Boolean values by faking it using ints that was correct internally but NC standard C++ actually does support a bool data type bool and you can declare a variable as a bool the constants true and false are defined. So you can use all of them except that internally it is immediately represented on the integer and you are allowed to abuse inter conversion between integers and booleans. So it is just a language support internally it is not strictly separated from the type of integers. Operators have their own precedence rules just like numbers for example and binds more strongly than plus than odd. So the expression you see over here I will just write it down copy it down here look like that and the corresponding operator trees as follows suppose I take just e less than equal to f the value e flows in the value f flows in into a relational operator which compares the two and remember the thing flowing here is an int or a float or a double let us say int but the thing that floats out of here is a bool and that goes to a not operator this is a not operator and that of course also outputs a bool according to the rules of boolean algebra. Now the next thing that happens is on this side it is not in this order actually a is compared to b plus 1 these are arithmetic operators so the incoming values are say float ints or doubles or floats and then this is also say an int a goes in say as an int it could be a float in which case it will be converted and then the equality operator tests if they are equal that outputs a bool ok. Meanwhile the second subtree looks at the values c and d and applies a relational operator not equal to here so this test outputs a boolean again out of this expression now there is a choice there are two operators and an odd and and binds tighter so the and happens first that outputs a boolean in turn and this gives you an odd and these combine to give the final boolean value out of the root ok. So that is the expression tree corresponding to that logical expression any question so you can read the rules of what binds harder than what operator in the c plus plus manual and if you are unsure you can always use brackets to enforce what you want. So to be safe if you are not with at the moment always put brackets so that the intended meaning is implemented and why are logical expression useful so far we have been computing only with numeric or character expressions logical expressions are used to control the execution of statements which we will start today. Now how do you assign values to variables as I started out saying it is pretty simple you compute the value as the right hand side then you say left hand side equal to right hand side for now the left hand side is just a variable name and the right hand side has to be an expression compatible with the type of the left hand side ok and as we saw in a previous lecture you have to be careful of the implicit type of the right hand side because you might say you know float f equal to 7 slash 3 and 7 will be interpreted as an int 3 will be interpreted as an int 7 slash 3 will be interpreted as integer division which results in 2 and then that will be assigned to the floating point number as 2.0. So while doing assignments you need to understand the type of the left hand side and right hand side fairly well ok. The main new material for today is what we call compound assignments or assignments with side effects and so on and incrementing assignments. So suppose our spec is that we have to read 2 numbers from C in and print the sum of their squares. So we implement it as follows we say int sum equal to 0 and num we read num from C in then we say sum plus equal to num into num ok this is short hand for sum equal to sum plus num into num and this short hand is provided for you know typing ease but also internally it might sometimes be slightly faster because sum is loaded into a register and then something is added in place rather than loading 2 registers and storing it to a third register and then writing it back to the same variable ok. So this may be slightly more efficient to implement then you read num the second time and do the same thing so you can keep doing sum plus equal to ok. This is not the property of plus alone you can do it with pretty much most operators. So if you are going to print the product of all these numbers you would say sum star equal to whenever you can put a operator ordinary operator you can put it in front of an equal to and that is called an assignment operator or a compound assignment. Now how about the effect of this? So you say int VA equal to 5 and then you say int VB equal to VA plus equal to 2. This is called an expression with a side effect. So if you look at the second expression we are computing VA plus equal to 2 that is an assignment that is assignment itself as a value. The value of the assignment is the value that was assigned to the left hand side VA after the expression 2 was evaluated and then the value of that whole assignment will go to VB again ok. So let us look at what happens if I run this code. So I will comment out the other code VA equal to 5 couple of things we can try. So we initialize VA to 5 we say VA plus equal to 2 and assign the value of that assignment expression to VB then you print out both of them. So we get 7 and 7. So assignments sort of cascade ok the value that is assigned to the left hand side can also be taken out and assigned as an expression to another variable and you can keep doing this. Initializing variables but here is another form called the increment and decrement operator and that is a little more interesting. So a special case of compound assignment is the syntax called plus plus VA or VB plus plus. Similarly VA minus minus and minus minus VB ok. So if you prefix or suffix a variable by plus plus or minus minus and that variable is has a numeric type. By numeric type I include character unsigned character signed and unsigned ints shorts floats and doubles and longs ok. Plus plus VA means increase VA by 1 and then access the incremented value whereas VB plus plus means access and remember the current value of VB and use it in whatever expression will be requiring it but then increment it before any further access. The second one may be slightly inefficient because the old value must be remembered in a register ok. The way you implement VB plus plus is you would copy the VB value the old value into a register. You increment the register corresponding to VB maybe you would store it back and then if any expression wants the old value of VB you have to copy it from that register again or access it from that register. So for example if we have this expression VB equal to 2 star star VA plus plus I will just copy it here. Now how would this be evaluated in some kind of a low level language ok? VB equal to 2 star VA plus plus. So in very low level terms what would happen is you would say load VA into say register 1 then you would say copy R1 to R2 right then you would say increment R2 then you would say store R2 to VA then you would say load constant 2 in say R3 then you would say R4 is assigned R1 times R3 the old value remember and then you say store R4 to VB ok. That would be the low level assembly language description of how this code would execute roughly speaking you could use registers as you wish. Now this kind of auto increment and auto decrement you have to use it very carefully because they are expressions but they cause side effects they change the state of the memory. So let us look at an expression here so it is a plus plus VA and then I will print out both. So 5 I increase 5 and then assign it to B and then I print out both. So I should print 6 in both cases so you get 6 and 6 right. Whereas if I say VA plus plus then the value that VB gets is the old value of 5 but VA afterward changes to 6 before I can print it out. So I get 6 and 5 let me try to put this side by side so you can. So you get 6 and 5 VA is 6 after incrementing but VB is 5 which is the value previous to incrementing. So that is the first expression. Now the reason why you need extreme caution in using this sort of expressions with side effect is that C plus plus uses lazy evaluation or short circuit evaluation of Boolean expressions logical expressions. For example look at the upper part of the code I declare variables VA and VB I read them in and then I have VC equal to 5. Then I say if VA is greater than VB and plus plus VC is equal to 0 then do something. It does not matter what it does later on I print VA, VB and VC. So what does this say if VA is greater than VC and VC on incrementing becomes 0 after incrementing then do something. So observe that this is a Boolean expression with an AND and suppose I find that depending on the input VA is less than VB. So the first clause of the AND if it is false then the AND is false and short circuit evaluation means that C plus plus will not even evaluate the second logical expression. So the plus plus VC will not even be executed whereas if I give values where VA is indeed greater than VB then there is a chance that the AND may turn out to be true or false depending on the value of the second expression. Therefore the second expression has to be evaluated no matter what VC is and so VC will get incremented. So let us try a demo. So in the first run I will input values where VA is less than VB. So I will say 3, 4 and as you can see 3, 4 and 5 so nothing happens to VC. VC was declared as 5 the same 5 is printed. Whereas if I input 4, 3 then VC has been incrementing just because of evaluating that expression. So this is the reason why you should try to avoid having expressions with side effect inside Boolean expressions because the Boolean expression will evaluate in the cheapest possible manner and clauses may be omitted depending on whether the compiler has already figured out the value. So and it makes code hard to read the behavior of the code will depend strongly on what the input values are to the Boolean expression and nothing is evaluated in full. You see the code there in the Boolean expression does not mean that all the clauses will actually be evaluated. If it is plus plus then the original value is lost you get 1 plus the old value. If you say VA plus plus then the original value is remembered. Any other questions? Yes? Let us discuss with a hub you know star shape. So any other questions? I will repeat your question and then we will discuss it. So that is the danger of side effects but sometimes you want side effects to write small clean expression. We will see that when you come to arrays. These are particularly useful for indexing arrays. You have an index you want to increment it as you run through the array then plus plus is quite handy. Another feature that C plus plus provides for short simple coding is what is called a conditional expression. A conditional expression has the form a logical condition which is either true or false upon evaluation then a question mark then a value you want to return from the whole expression if the condition is true then a colon and then a value you want to return from the expression if the condition was false. For example if I wanted to write down the expression for the maximum of two numbers a and b I would write it as a greater than b question mark a colon b. So this is very easy to read if a is greater than b then a else b. So it is an expression form of the if statement. So in if statement you check a condition and then you execute one of two possible branches here you check a condition and evaluate two possible expressions. Now another example suppose you want to return a divided by b but rounded up to the next integer in case b does not divide a evenly. If a is divided by b evenly then you want to return exactly over b otherwise you want to increase to the next integer. So the second expression is technically type correct. So you say a percent b greater than 0 if a percent b is greater than 0 that means there is a remainder and therefore return a over b plus 1 here otherwise just return a over b. The one that abuses C plus plus conflation between Booleans and In says a percent b question mark a over b plus 1 or a over b. Now note that there is lazy evaluation and therefore you should avoid side effects like a percent b question mark c plus plus d minus minus. Here depending on how this first condition evaluates exactly one of those would be executed and so the side effect would be data dependent. Generally speaking you want the side effect to show up clearly in the code not as a function of input values. Yes same that side exactly one of them will be but you will not know which one until you supply data. So it is good to make that explicit in if then else statements rather than use these kinds of conditional expressions to write your code. So they are saying there is actually a bool type. So old C plus plus used in to store Boolean values and it still does but to the outside world to the programmer the ANSI standard C plus plus offers a type called bool and there are constants defined called true and false but it is only a very thin varnish on top of the same basic machinery because you know you can instantly lift a Boolean value to an integer by saying int of a Boolean value and old bad habits are still allowed. You can say if 37 do something or you can even initialize a bval from 37. It will just automatically course to whatever true is and zero is false. So overall value is unclear but you can use it if you think it makes your code easier to read. So zero is false everything else is true. So try to avoid this feature like the plague try to make your intention clear by actually completing the relational operator like a percent b greater than zero. Eventually someday someone else will read your code and find it easier to understand. Okay so that finishes the module on expressions and their assignments to variables. Now you know generally speaking it's no fun if we are always writing straight line code. So far we have a one main function and inside there is a sequence of statements which is just executed in sequence one after the other irrespective of what the data values are. So now we will get into controlling the order of statement execution. We have seen bits and pieces of this in recent labs but now we will look at this formally. The first thing is that in the body of main that we already wrote there were not just one statement but a sequence of statements S1, S2, S3 etc. So statement colon semi colon statement semi colon and the semantics of that is very simple no matter what happens keep executing them one after the other and by convention zero or one statements are allowed for uniformity and instead of just allowing this inside the body of main we will allow what's called a block. A block is nothing but a curly bracket followed by zero or more statements separated by semicolons followed by close curly bracket. The body of main already looked like that but we will allow nestings okay. So for example you are allowed to say something like this. You can declare an int value do some stuff and then you can open another curly. You can do some more work there. You can close that curly and then you can close off main. So what does that new set of nested curly brackets do? Anytime you say a curly bracket followed by S1 etc up to SN that means that these statements look like one statement. They are a compound block statement which is consisting of these individual statements executed one after the other. So anything you state here will just execute like that straight line fashion. So so far it seems to be serving no purpose but there is one interesting point regarding variable naming. Suppose inside this inner curly I declare int b. At this point in the code you can access both a and b. b is known from here, a is known from there. But once you come out of this curly at this point in the code b is unknown. Technically we say that the scope of b has closed and b has been destroyed for all practical purposes. The memory for b has been released back into the C++ runtime system and at this line if you use the variable b you will get a compile time error saying I don't know what b is. Now that is actually a feature. The reason is that suppose writing a long procedure or function and then other people will modify it. You have one loop here another loop there. Suppose you start sharing variables across them then you might make a mistake about the initial state of the variable or what was the assumption when you entered into your block of the code. If you conscientiously use these curly brackets to isolate big chunks of code from each other then variables used in one block will not be reachable by code in another block. You will only transfer what variable should be shared. So for example if you have here is the first block of code here is the second block of code they should only share a variable a but they use their private variables b and then the next the person who programs next on the project also declares a b. These two variables are completely different. They have no connection with each other although they are both called b. This b was destroyed when this curly closed and then the new variable b was created. So there is autonomy inside the blocks provided they don't share variables from the outside. That is one big purpose of Curly's. The other thing is that if you code in a straight line like this then of course Curly's are not too useful. They become more useful when you combine them with other constructs like if then else or while loops and so on. So for example if I wanted to re-implement my say maximum of two variables suppose I want to store in the variable b the absolute value of variable a. So then I can start off my code saying int a b and then I can say read a from c n. If a is greater than equal to 0 then b is just a a from c n and then if a is non-negative then b is just assigned to a. Otherwise b is assigned to minus of a. I could also, so we have already seen a shorter way of writing it. We can use expressions. So I have already seen that we have other means of writing this stuff. For example we could say b equals a greater than equal to 0 a minus a that also give you an absolute value or even in the if then else world if you didn't need a new variable b but you could clobber the old variable a then you could just say if a is less than 0 then a equals minus a. This would destroy the old value of a and just store absolute value of a in a itself. So in other words the else clause can be missing. The else clause is not compulsory. Now here is another example stored in the variable c the smaller of the values of variables a and b. So we declare int a b c and read a and b. If a is less than b then c equal to a else c is equal to b. So that's how you take the minimum of two values. The else part is optional and you can also cascade or nest. Any such construct in c plus plus you can indefinitely nest. Now statement blocks are also optional but they are best used. For example so I could instead write I could do that without the curly brackets. But the danger here is that this is visually a little misleading because you could say something like equals some stuff and even if it's intended the else clause has finished. So it's generally a good idea to put curlies even if you think you don't need them so that any programmer updating your code are very clear about whether their new statement goes inside the curly or outside the curly. You can avoid a lot of bugs in this way. Now as I said you could keep cascading this or nest this. So nesting you could of course do things like if condition 1 and then inside you could say if condition 2 and then you could say else and then do something and inside here also there could be another if statement if c 3 etc. So any kind of nesting is freely allowed. Not only that there is this form of a cascaded if which looks like if day of week equal to 0 then do something else if day of week equal to 1 do something else else if day of week equals 2 etc. Now this is within the language what's happening is you have an if statement and the condition is a test against 0. So suppose this is statement 0, suppose this is statement 1, suppose this is statement 2. If the if condition is true then you execute statement 0 otherwise else this is another if statement starts here. So this is the if where the test is 1 if that is true you execute 1 otherwise there is another if statement and nothing happens if the last test fails. So when you cascade if statements like this it's like a spine of s's running down like a tree but chain like tree is chaining the statements. Now one important thing to note here is that suppose my test look like this suppose I say d o w is a variable which is value 5 and suppose here the test is d o w percent 5 equal to 0. Then actually two conditions are true but that doesn't matter because as soon as the first condition qualifies say equal to 5. If the first condition qualifies control comes down into s 0 and it doesn't go down the right hand side. So even if multiple conditions in this cascade are satisfied only the first one will be executed this will not be taken. So when you read a cascade of if statements always think of it in this form of a tree. Just like expressions the C++ compiler will immediately try to turn your code into a also a tree for the statements with the construct like if then else and why. Now for example suppose you are withdrawing money from a bank. So you are writing code form for the ATM machine. So you read from the keypad which will call C in the amount to be deducted. Now if the amount to be deducted is more than the balance then the bank should prevent you from withdrawing money. So it's an account overdrawn and finishes the transaction otherwise it says successfully withdrawing deduct amount of rupees and then it reduces the balance by the amount to be deducted. You have to also make sure that same amount of paper money is ejected from the machine otherwise customers will be very unhappy. So the entire area of databases and transactions in computer science deals with software that will ensure that either none of the two things happen balance reduction and money production or both of them happen. That's called an atomicity of a transaction you want the two things collectively to happen together or not at all. So we won't go into that of course in this course but that's an important area of computer science. Now you can also write the then or else parts without curly brackets but that could be dangerous as I was saying. If you write code like this then even if it's indented the plus plus n statement is outside the scope of the if okay only the first statement is inside the scope. Now we've also seen conditional expressions. We can rewrite the earlier examples as B is a greater than 0 A or minus A or C is compare A and B if A is smaller take A otherwise take B okay. If in doubt always use parenthesis to make sure the expression tree is correct and note that nesting quickly gives unreadable code. So A is greater than 0 test A otherwise minus A less than B then 100 plus C or C minus 100. So this becomes very very difficult to read very quickly. Also as I said before never use or avoid using side effects inside these kinds of expressions or code will be difficult to read okay. Now earlier I was showing you this long cascade of if then else where I was testing the day of the week against 0 then against 1 then against 2 to decide what to do okay. Now that's of course painful to type and that's why the switch statement was provided in C plus plus and other languages to test the value of a variable like day of week and look at various cases of it okay. So you could say case 0 then print Sunday case 6 you print a Saturday and for any other value you print a week day okay. So there are these special keywords let's go through them one by one switch says you're starting a switch statement based on a variable called day of week that variable is not allowed to be a float it's not allowed to be a string it can only be a discrete variable type like character or integer okay or long integer and short and these values are possible values of that. So if in case day of week is 0 then do this in case day of week is 6 then do that. If none of the conditions are satisfied then do what's called default that's the syntax default always comes last in the switch body. Now one important thing is that is this break statement here right the break statement takes control from this position to the end of the switch statement the break terminates the switch statement immediately without considering any of the options afterwards okay. So it's vital to remember to type break and it's a very common source of bugs okay. So the day of week can be character in long and short etc. If you do not put the break at this point control will just fall through to the next case and in fact the case will not even be checked we shall see that in an example. So if this break was missing then you just print suppose day of week was 0 you print Sunday but then also print Saturday and then break. So remember to always put a break here and also if you want to declare local variables inside the case body always put curlies to shield those local variables from the code afterwards. So let me show it here so if you have something like that and to do the processing for the case 0 you need to declare some variables like that. Put a curly around remember to insert a break so that if here someone wants to use VI again that will be isolated from that they shouldn't be connected okay suppose someone forgets the break this VI carries over that's dangerous coding. So to be defensive in your coding always put curly in the cases as well unless they are single statements perhaps and if you're declaring variables always put a curly so that the variable doesn't survive beyond the case okay. So you need to kill the variable before that particular case is exited yes. If you remember to put the break then that is how the language was defined. I'll show you so let's look at yeah so int val equal to 5 switch val so since I didn't write the compiler for the language I don't know why it was defined this way I think it's for implementation cheapness. So int val equal to 5 switch val case 5 c out 5 suppose you forget the break after that there is a c out 4 okay and then break and default is default okay we just printed out so let's run this code and see. So day of week is 5 test the 5 comment out that break and so on okay. So 5 is printed and 4 is printed even though DOW does not match 4 so this to me is a major problem with the language yes so let's test it out right so you're suggesting that after the 5 I put a scope like this right I forget the break and I declare say int i x a right say like that yes and then at 4 what do you want to do another similar thing right this time we say don't forget the break but I declare i and t i x again equal to 7 right. So I don't think the compiler will complain I think the compiler will go through fly now suppose you want to print i x here of course that i x will be this i x no in fact even if you declare the 6 right outside here the local scope will dominate the global scope okay. So let's check that so it's 7 not 6 the inner i x will take precedence over the outer i x yes no so this i x ceases to exist at that curly after that it has no effect this is exactly why curlies are very useful you make an ambiguous the scope of a variable yeah yes we'll discuss for later I don't want to confuse the we'll deal with for in the next lecture okay. So to me this is actually quite confusing why in spite of dw not matching 4 I drop right into 4 okay and the reason is that internally and I was quite surprised to see this actually and I've not coded c++ for a while so internally what happens is those case parts those are lined up in low level language like this okay and the compiler remembers the entry point into the various cases okay then when control enters the switch statement the compiler has something like this compare the switch variable against the first value okay if it is true if it is equal then jump there all right and if you put a break here that is basically what's called a go to statement to the end of the switch okay if you forget to put okay suppose I check for the second value and I do a jump there in case of true if I forget the break so this is a break here there was no break here control just drops to without a comparison control flows through here and then goes straight down the comparisons don't happen one after the other unlike the cascaded if so the switch is not the cascaded if exactly okay so this is very important to understand so code conservatively use the switch how it was intended to be used don't drop the breaks then things will be fine otherwise you might get all kinds of funny effects okay so that's the switch statement now so see if you can find out more about how this switch is implemented by looking up the web and try to explain what goes on by looking at the generated code okay in the sense that how web pages write about how switches are compiled here's another useful application of the switch statement suppose we want to distinguish between characters based on whether the vowels or not this time the fall through is a feature okay this is exactly why the fall through was allowed to be what it is which is slightly different from cascaded ifs so you say switch ch case a case capital a e and capital e all these cases you print it's a vowel okay otherwise in the default case you print it's not a vowel so in this case syntactically it's much shorter to write this just put down all the cases which should be handled by one kind of action and then put the others in a default so yet another switch example suppose we want to build a trivial calculator which can deal with a few binary expressions so there's the left operand the right operand and the operator and we read them in sequence after that we print out whatever expression was given in and then we switch on the operator since the operator is a character it's a discrete type and we have four cases plus minus multiply and divide and then we actually do the operation and print it out okay if the operator does not match any of our standard operator supported then we say illegal operator and finish up so that's another simple switch example any questions about the switch so we have if then else we have switch we have cascaded ifs we have nested ifs of course you can nest a switch if you feel like there's nothing preventing you so now we will start with loops because remember last time we were doing some bit arithmetic on a bit vector or an integer if to do anything you have to you know repeat it 32 times in the code to handle 32 bits that's very painful so loops will of course help a lot so of course the primary role of a loop is to keep repeating doing something for example you can say while true which is while condition we have to keep doing something so I will lecture clearly or slowly or you might say I will remain quiet in class this will just keep on printing it without ever finishing if you want to quit the program you have to hit control c of course this is also no fun because insanity is doing the same thing over and over again with and expecting different results that won't happen so instead we'll have to change something in the body of the loop okay so here's one other example of a loop slightly more sophisticated keep reading input numbers forever and check if each number is greater than the previous number read so the logic for doing that would be to remember the previous value in a variable called prev and then read the current value in a variable called car and compare preven car and the important thing is that at the end of each iteration we will overwrite prev with car of course we don't have to remember all the values entered so far it's enough to remember just the last value now after that there's some mess here but I wanted to just introduce you to the joys of in a standard C++ programming now in the in the beginning the first number cannot be compared with anything before but by definition the first number is an increasing order the smooth way to implement that is to pretend that the very first number entered or the number before the first number was minus infinity or the minimum possible double number so in C++ you implement that by including limits and then you say numeric limits of double min okay this looks very very arcane but you'll soon get used to it this basically says of the type double find me the minimum limit but you can also replace it by some very large magnitude negative number as you wish and then while true we keep on reading there's no end to this loop we declare double car we read that in if car is less than equal to prev then it's not in increasing order and so we print out not in increasing order otherwise or even otherwise you know we in any case assign car to previous so this is clear suppose we wanted to quit the loop as soon as the first violation happens then after this see out we can do a break a break will leave this loop but break will discuss in a little more detail in the next now another example is printing an integer in binary this is slightly more interesting surprisingly standard C++ will let you print a number in decimal and hexadecimal and octal base 8 but there is no predefined library function which prints out a integer or a byte or a short in binary format but it's simple enough to implement for brevity consider printing a byte number called num take the bit pattern mask which is set to one followed by all zeros let's do a bitwise and between num and mask if the result is nonzero then we print a one otherwise you print a zero and then we shift the mask right so that the one shift to the next position then the next position and so on right this way we can print the whole number in binary but we can do this more efficiently without using a mask by shifting so instead of shifting the mask right we shall shift the number left so we'll use a fixed mask of one followed by all zeros which will not change say the number is 107 in decimal which looks like 0 1 1 0 1 0 1 1 the first masking action will take one followed by all zeros and mask it with that number and this will get a zero because the leftmost bits are one and zero whose and is zero so we'll print a zero then we'll shift the number left so that from 0 1 1 0 1 etc it becomes 1 1 0 1 0 1 1 and the last zero is padded from the right this time when I and one followed by all zeros with the new number which has a one in the leftmost position I'll get a one which is nonzero so I'll print a one then I'll shift the number again and continue like that observe that the numbers I'm printing 0 1 1 etc is exactly 0 1 1 and so on right so this is how I can easily print a number in binary but doing this explicitly eight times or 16 times or 32 times would be painful so I can keep doing this until num goes zero why should num become zero because zeros are inserted from the right as I'm shifting the number left eventually all these one bits will drop off the left end and the num will be replaced by entirely zeros so let's implement this and see that it works we don't need many of those things so let's say unsigned car which is a byte num equals 107 okay then we say while num is not equal to zero we print what do we print we say num and this is an unsigned car right so we say 0x80 that's the one with the leftmost one if this is nonzero then we print a one otherwise we print a zero we don't print the new line because we'd like to have the bits next to each other okay and then finally we print a new line let's see if that works out oops where is the bug the I forgot the shift right shift num left by one otherwise we got an infinite loop so that's the number in binary yes yeah unsigned car so in this particular case it would be okay cool down okay so here here's one request if you want to make noise don't use institute property so no desks only claps but quietly so so if you declare unsigned or signed it doesn't matter in this case because you're shifting left if you had to shift right then it would make a difference okay nothing nothing particular to show all right so we just get into the habit that if you're doing bit mass corporations it's always safer to declare unsigned because only zero bits will come in that's all so that's how you print in binary that's a shortcut until num becomes zero so the the question was what happens if the number has a zero in the least significant bit so 106 is even right okay in fact if 107 is odd 106 is just zero in place of one there so let me compile and run this ah so that's an interesting observation so so what happened here okay so that's good of you to catch yes so if the num is turned to zero then there's a problem in the last position right so how can we fix that the last division turned into zero in fact if the number is a multiple of four then we are in even more serious trouble right so suppose I say 16 okay this is completely bogus right so what's happening here so clearly this is buggy yeah yeah so so clearly you know let's clap less and think more right so so what's wrong with this piece of code we need to understand the word size and continue going so the test is wrong right so we can change the test how do we change the test so you could just say you know because I know the input is and by it will just go eight times okay so we can say int step equal to zero okay and then we say while step less than eight and then we can increment step right so that should do it the next example is even more interesting so suppose I want to raise a number to an integer power so we are given a double precision number called base and we are given a non-negative integer power int power say and we want to find base to the power power now we'll look at a simple and then a more efficient version so so we initialize a variable called answer to one and to do which is the number of multiplications to do to power and while to do is greater than zero we multiply answer by base which you can either write as answer equal to answer star base or answer star equal to base and to remember that we have finished off one of the multiplications we decrease to do by one so minus minus to do and we do that clearly this is correct so this is obviously correct but it's interesting to prove the correctness to ourselves by using what's called a loop invariant okay so initially answer equal to one and to do equal to power now you can convince yourself that after any number of iterations this quantity answer into base to the power to do is base to the power power there are multiple variables so look at it very closely while keeping quiet okay so this is a formal statement of what the loop does so the statement is that iterations don't change this relationship between variables okay answer into base to the power to do is base to the power power initially answer is one and to do is equal to power so clearly initially this condition holds every iteration to do decreases by one but answer is multiplied once by base so every iteration this expression remains true and finally to do becomes zero so base to the power to do becomes one and so answer has to become base to the power power okay so the number of multiplications involved here is exactly power I take answer and multiply it power times by base okay now there is a much more efficient way of doing it and it's called the doubling method to understand that let's consider a special case where power is a power of 2 so let's say power equal to 32 instead of writing out base into base into base 31 times 31 multiplications like we are doing effectively we can now write a variable B2 for base squared and instead of using base ever again we can say B4 is B2 into B2 that gives me base to the power 4 then I find base to the power 8 base to the power 16 and my answer is base to the power 32 okay so and this cost me only 1 2 3 4 5 multiplication instead of 31 multiplications okay so it's about log 32 multiplications so how can I implement this for the general case where the power is not a power of 2 suppose power equal to 29 and imagine that 29 is a byte so we can write down things in brief we can express 29 as some sum of some powers of 2 so it's 16 plus 8 plus 4 plus 1 that is 29 therefore my answer is base times B4 times B8 times B16 if I computed all these powers of 2 I can put them together with a few more multiplications to get base to the power 29 so now let this variable Bx take values 0 through 7 this time you know stepping up from you know from the least significant end to more significant bits okay we keep doubling as before and if the Bxth bit of power is 1 we include the power in the product otherwise we don't it's very simple right I will compute I can compute B2 or base to the power 2 on the way but I'll just not multiply it okay if if the Bxth bit of power is 1 then I do multiply now you already know how to get a bit by using val times 1 okay so this will be a much faster code so unsigned in this time we need an unsigned because we'll be shifting right okay unsigned int to do equal to power double answer equal to 1 and term equal to base so term will be reusing term for all those values we'll just go through them without preserving the old ones because you don't need the old values while to do is greater than 0 we will do the following if to do and 1 is equal to 1 then we will multiply answer by term in any case we will double term and then we'll shift to do so let me write down this code let me write down this code on board so we can track it with a value okay okay the if ends without an else clause and then I double term this will do the same thing as that expression term star equal to term and I shift to do which I can also write by saying to do slash equal to 2 okay I'll half to do and I end the following so let's now trace this code on paper so let's take the specific case where of 29 okay let's say power is 29 0 0 0 1 1 1 0 1 okay that is what power is which is to do initially now the first test I do is to do is greater than 1 sure so I get into the loop now I take to do and look at its least significant bit by ending it with 1 and that is equal to 1 in this case so what happens to aunts so answer will so remember initially term is equal to base so at this point answer will be equal to base right after that term will be doubled so term will become base squared and to do will be shifted right by 1 so to do will now become this time after ending it in the next loop iteration I'll end it with 1 and find that it's a 0 so answer will now be still be base okay I will not multiply what term will become base to the power 4 because term is squared so term becomes base to the power 4 and I shift again so in the next iteration I get that 0 1 1 1 so this one has shifted here yes no see answer is updated only in the case that the least significant bit of to do is 1 otherwise answer is not updated fine so answer remains be in this case then term increases to be to the power 4 in the next iteration I actually find the lsb to be 1 again so now answer changes to b to the power 5 whatever answer was multiplied by b to the power 4 and term then become b to the power 8 and I shift to do so to do now becomes again I find this to be equal to 1 so now answer becomes b to the power 13 8 plus 5 okay so what I am basically doing is I am choosing powers from here I choose this power I choose that power this power right this number so far is 13 it's you know 8 plus 4 plus 1 and I have now shifted it up to that point so I have taken b to the power 13 meanwhile this becomes b to the power 16 term star equal to term in the very next iteration I get the last one okay so now I multiply those two to get b to the power 29 and then I shift it once again and I get all zeros and so I exit the loop okay I end up with b to the power 29 as I wanted but the total number of multiplications is much smaller okay so roughly speaking you can cut down the number of multiplications from linear in power to logarithmic in power okay so the library functions called power in C plus plus and C they implement something even smarter than this inside okay so if you are doing it only once or twice then this is no big deal but if you have the computation of a power of a variable because you are solving some nonlinear differential equation and that's inside a very tight for loop which executes trillions of times then saving the number of multiplications is very very important okay you can get huge speed ups in your code by using this trick right so that's for general powers so that's what the faster code will do okay any questions about the progression from calculating powers in the easy arithmetic progression way to the doubling way so how did you come up with the idea we looked at the loop invariant we said well you know we don't need to just decrement to do by one at a time we can you know double the value or square the value rather okay rather than doubling it you call it squaring so let's try out this code and see some funny effects okay so fast power dot cc so I have a base variable which is 2.3 and power is set 10 I'll compute two values the slow value on the first value initialize both of them to one in the slow method to do is power while to do is greater than 0 slow star equal to base minus minus to do okay then I print slow and in fact I also print f it to a enormous number of significant values okay in the fast method it was as I said term equal to base unsigned to do equal to power while to do right shift to why to do is greater than 0 that exact same code over there I can either you know do term to do slash equal to 2 or to do equal to to do right shift 1 same thing then I'll print the fast value again to small precision and to large precision finally I want to compare the fast and slow values okay just to see if they're the same so fast equal to slow then equal otherwise not equal okay and ignore the last two lines for the time being so this code is clear right I compute base to the power power in two ways the slow way and the fast way okay so let's compile this now I'll run that and it claims the slow value is that to more precision it looks like this the fast value looks identical and it looks like that and they're not equal so the look equal why are the not equal so in the last two lines what I do is something that we haven't covered and will not cover for quite a while but it's probably worth just you know telling you what it's doing but then you know not worry about it too much what I do is I take slow and I take its address in memory that's done by an ampersand operator then I tell the C compiler I fool the C compiler by saying that although it was originally a double the double is the same as the long it's both eight eight bytes okay so pretend it's actually a pointer to a long integer and then print out that long integer in hex okay in this case I take fast I take its address in memory I fool the C C++ compiler into thinking it's a pointer to not a double but to actually a long integer and I print its value in hex okay you can learn about this offline that's not so important what we'll see here is something else so let me compile this code again when I run it you see it's not equal oh I didn't save that fly so you see it's not equal because the last bit of the mantissa was different okay so it's the very last bit in the double precision number when printed out to a few digits of decimal it didn't make any difference but the in memory representation is off by two bits actually this is 101 in the end this is 110 in the end so it's very small significant bits of the mantissa which were different and so the test for equality failed okay so remember that when you speed up algorithms by this kind of numeric tricks you may not get exactly the same value as with slow methods okay and so any test of equality you do has to be corrected accordingly you have to now test to a threshold okay so I'll continue with the next example in the next lecture