 Good morning. So, last week we saw a particularly elementary model of computing for an artificial Dumbo. Primarily we understood the notion of memory locations, the fact that memory locations are associated with names and in those memory locations values can be kept. We also saw the Dumbo model permitting us to collect values from us as input, do some simple computation and upon our instruction to output those values to give those values back to us. Essentially then we now switch over to the discussion of real computers. There are multiple views that you can look at a computer through. One of them is the operating system view which is what we described briefly that in order to write and execute programs you have to first learn about the operating system which is the manager of the overall computing environment and in fact the first week lab which some of you would have done others would be doing during this week you would become familiar with that interface. However our primary objective is to learn programming and therefore we continue our discussion now. We move over to proper CC++ programming environment and see the facilities that are provided in that environment. We start with another example which requires some computations and in the context of that example we will see what are the different type of values that can be handled by the machine as seen by a CC++ programming environment. We will briefly look at the internal representation of numbers done by the computers. However we shall not dwell upon it too much and we shall not use that internal representation in most of our future lectures because we shall not be seeing the raw machine ever. We shall actually be seeing it through the eyes of a CC++ programming language and the facilities given by the compiler of that language and therefore we shall restrict ourselves in subsequent discussion on how memory is allocated to objects in our programs. What are the rules of computation that the programming language provides? More specifically we will look at the notion of an assignment operation where a computed value is put inside the computer's memory at the specified allocated location. We will then look at the computational operators which constitute our expression and therefore we will look at the expression evaluation process. The last three points where I have said more examples where I have said need for selectively executing a group of instructions and facilities for conditional execution. So we are saying that some large Indian oil company has erected cylindrical tanks to store oil. These tanks have been erected on a large rectangular field. Let us say these tanks are old and they need to be painted and we wish to determine the cost of such painting including the flat circular cover which will be on the top of these cylindrical tanks. Obviously the bottom of the tank is grounded so there is no question of painting that. Since the price of painting is quoted always in terms of rupees per square meter we will need to calculate the total square meter of area that needs to be painted. So obviously if there are n tanks calculating area of one tank and multiplying it by the number would get us the total area. The surface area of one tank given the radius r and height h you all know the formula for surface area of the cylinder. The area of the outer surface is 2 pi r h and then there is a circular cover on top of the cylinder whose area would be the area of the circle pi r square. Consequently the total area for n tanks will be n into 2 pi r h plus pi r square. That much is obvious there is no confusion there. So all that we see is a computer program which will permit us to read the values of r and h. It will permit us to read the value of n the number of cylinders and it will also permit us to read the price per square meter of painting. Given all these values we can just substitute these values in the formula and get the computation done. The program that I would write would look something like this. So you see the first line here this is again a comment line I do not know whether I use this style of comment in any earlier program sample or not. We always started a comment with slash slash. So instead of that this is another style where you start a comment by slash star. Then you can write not just one line but you can write two lines three lines four lines whenever you put a star slash that ends that comment. So multi line comment if you want to write. Quite often you would like to describe who is the author of the program for what purpose you have written etc etc some kind of a documentary of five or ten lines at the beginning of the program and it looks silly to keep writing slash slash for every line. So you would typically write a slash star write eight ten lines a comment and you put a star slash in the end. The c++ compiler completely ignores all lines between slash star and star slash. So it presumes that is command meant for human readers not for me. Next starts the program. This goes around the familiar lines. We have include IO stream using namespace STD. Again things which we said we will just take in our stride and write as of now just as it is. Int main is the starting of the main program. Actually it is this brass opening brass which curly bracket which starts the program and ending curly bracket ends the program. In fact all kinds of brackets that appear in our program must always occur in pairs which is common sense in using any brackets. The main program itself says float r h pi equal to 3.14159 price. Notice that I am declaring so many names here. I am also declaring an initial value for the name float pi. Although such assignment of a value should ordinarily be done in an assignment statement as we shall see for initial value such an assignment can be done in the declaration as well. The number of tanks will be an integer value necessarily. So we declare it as end tanks. We forgot to include a name for the final cost that we compute. So we add another declaration float cost. Then there are a series of output and input statements. The output statements will cause c plus plus compiler to show us a message on the screen in response to which there is an input statement. This is a typical style of input. Before every input you give a meaningful message to the user saying such and such input is required. So you say c out give the radius and height of the cylinder followed by another statement c in r and h. Notice that semicolons complete a particular statement in c and you can write as many statements as you want between two semicolons is a new instruction. That is the assumption that the c compiler makes. Similarly here I collect the information about number of tanks. Here I collect the information about price per square meter for painting and then as you saw in the previous slide I simply have to substitute these values in the formula. The only thing is multiplication is explicitly stated with a symbol star and rest of it is commonsense. So this is an expression which will calculate the value of the total cost for painting. This is assigned to a name cost which I output later on by saying cost of painting is so much. So this program is fairly well understood I suppose. It is in the context of this program of such programs that we shall be writing. We now discuss in more detail rather quite thoroughly the kind of values that we are able to handle in our program. The kind of names that we can give to the memory locations in which values will be stored and of course the rules of arithmetic computational operations and the assignment. To begin with we will briefly comment on the internal representation of data values. Although we shall not be dealing with internal representation for quite some time in this course because we are looking at values that we see. But still it is worthwhile to look at the internal representation to understand the restrictions and limitations which exist in real world computers while we do computing using them. It is well known that computers use digital circuits. Digital circuits can represent only two distinct states uniquely off and on. It is like any switch that you see on the wall. So switch is on, a bulb will be lit, a switch is off, there will be no light. This off and on states are usually symbolized by 0 and 1 and that is why you can imagine the computer memory as well as computer circuitry to be capable of internally storing a symbol 0 and a symbol 1 and that is all it can store. Consequently all information gets represented using only these two symbols. We use a decimal number system which is called base 10 but the same numbers could be represented in a number system of different base. For example a base 2 or a binary number system would have only two symbols 0 and 1. Now if you look at the decimal number system you have 0, 1, 2, 3, 4, 5, 6, 7, 8, 9. When you want to represent the next value there is no more symbol left. So after 9 you put a 0 in unit position and add 1 to the next position. So 1, 0 becomes the representation of value 10. 11, 12, 13, 14 like that we go on up to 19 and again we get stuck because after 9 there is no more symbol. So what we do is at 9 we write a 0 and add 1 to the next position. So it becomes 20, then 30, 40. At 99 we are against the mind. So we write 0 against this line then we see that left is 9. We again have to write 0 because there is no next symbol. In exactly the same manner when you have a binary number system which has only two symbols then after representing a value 0 by symbol 0 and value 1 by symbol 1 we are stuck. The next value which is number 2 not symbol 2. I am talking about value 2. Cannot be represented by a new symbol and therefore what we do in decimal system is exactly what we do in binary system. We write 1, 0 to represent the next value which is 2. 11 will represent 3. After that there is no symbol again. So this is a situation similar to 9, 9 in our decimal system. So after 9, 9 we have 1, 0, 0 but that value is 100 in decimal. We write 1, 0, 0 which becomes a value 4 in binary system. Those of you who have studied binary system can expand this but these are typical representations here. For example 10 to the power 3 is 1000 in decimal. 2 to the power 10 in binary notation is 1, 0, 0, 0, 0, 10, 0 followed by 1. It so happens that this value which you can independently calculate by raising 2 to the power 10 is 1024 in decimal. 1024 happens to be very close to 1000 and therefore it is termed as K or kilo. There is a problem here in that we do not know how to represent negative numbers. How do you represent negative numbers in decimal system? You write a sign minus in front of a number. The minus and plus signs are special additional symbols used by us in decimal number system. When you have large number of symbols like A, B, C, D, whatever you can do whatever representation you wish to do for any system. But a digital computer which has exactly two possible symbols has to use one of them to represent sign as well. Consequently one binary digit in any arrangement of binary memory is reserved to represent sign. Traditionally 0 represents plus and 1 represents minus. This is different from the numerical value that is represented by the symbols 0, 1, etc. These incidentally are called bits or binary digit 0 and 1. Continuing with our nomenclature when 2 raised to 10 is rooted as 1 K it is not exactly 1000, it is 1024. But just like you have 1000, million, billion, trillion which are all multiples of 1000. So 1000, 1000 is 1 million, 1000 million is 1 billion, etc., etc., in English language. In exactly same fashion there are nomenclatures which have been attached to integer powers of 2. So just as 2 raised to power 10 is 1 K 2 raised to power 20 is called 1 meg or 1 mega which is roughly equal to 1 million but not exactly equal to 1 million. 1 million will have 1 followed by so many zeros in decimal system whereas numerical value of 1 mega here will be 1024 into 1020. Well it is close to million when you go to that size of numbers. In exactly the same fashion 2 to the power 30 is called 1 giga which is 1000 or 1024 mega or 1 K million you can say. Similarly 2 to the power 40 is 1 tera and 2 to the power 50 is 1 peta. These large names did not mean much in the early life of computers in 50s and 60s. But today we routinely talk of giga and tera and peta. So these names will come across when we describe the sizes of modern memory and particularly the sizes of modern disk capacities. And within about 10 years humanity will be using 2 to the power 60, 2 to the power 70, 2 to the power 80, etc. Now the value of any number which is stored in a memory location the maximum value will depend upon the number of bits allocated to that location. It is obvious. Look at the drawers in the Dumbo model. We did not say so but we presume that every drawer has the same capacity and that capacity would determine what is the value of the number that you can put. In exactly the same fashion in actual memory location will have so many bits associated to that location and those number of bits will decide what is the largest value that you can ever put inside. Now the capacity of a memory location as seen by the C++ language compiler for that matter most language compilers is actually 8 bits. This is called a byte and this is the smallest addressable unit of memory. So you can imagine it is like a row houses where each row is one byte and you have a very large number of houses there each uniquely numbered. So the number of the house is like an address of the memory location and the quantity of the amount of information that you keep inside a location is limited by 8 bits. So you may have a million bytes or a giga bytes in your computer's memory but each byte essentially can store only 8 bits. Now this value which can be stored in such a location is too small. It is not useful for solving even routine computational problems. So what is the value that you can store in 8 bits the maximum value each one can be 0 or 1. Since there are 8 bits the largest value that you can represent is when you have all ones here right. So if there are 8 bits the largest value will be actually this value will be 255 256 is 2 to the power 8. If you had 8 digit decimal number the largest value would have been 10 to the power 8 minus 1. 8 9's basically. Since 9 is the largest symbol 1 is the largest symbol here so it will be all ones. What is the smallest value that you can store when it has all 0's. So this is actually just 0. Now if you use a byte to store only positive integers this is the range of values that you can store. But as I said you would like to store negative numbers also. You have to have some notation for negative numbers. The only mechanism that we can have is to allocate one of these bits to represent side and that is what is done. This bit which is called the most significant bit is associated with side. So this will represent plus or minus. 0 will represent plus and 1 will represent minus. If we take that notation then what is the range of values that you get? On the plus side it will be 2 to the power 7 minus 1. This is the largest positive value. On the negative side it will be minus 2 to the power 7 minus 1. This becomes the range there. Observe that by allocating one bit for side we are actually losing the capacity to represent one number. We represent one number less. The earlier range was 0 to 2 to the power 8 minus 1. Now the range is minus 2 to the power 7 minus 1 to plus 2 to the power 7 minus 1. The number 0 gets two representations. Can you indicate which two representations you get? Plus 0 and minus 0. Now this could be quite confusing even to a computer. Consequently this is not the method that is used internally. Internally the machine uses a mechanism called two's complement. Those of you are interested can read more about it. It will permit a single representation for 0. However as far as we are concerned we are neither worried about the two's complement nor worried about whether this bit 0 means plus 1 means minus etc. Nor worried about binary representation of numbers. This is just for our information that internally this is what will happen. All that we note from this discussion is that one byte is to priddle a thing to be meaningful in our computational problem solving. It is not possible. Consequently what we need is the ability to process values which are stored in consecutive bytes, not just one byte. In fact modern computers do permit us to combine consecutive bytes to represent information and to process information. The typical combination of such consecutive bytes is two bytes, four bytes or eight bytes. You could even have seven bytes, you could have 334 bytes but this is the common grouping that is made available intrinsically at the hardware level of the computer. Naturally any programming language which is implemented on the computer first attempts to exploit this natural grouping which is possible within the computer and later on tries to extend it by artificially creating larger groupings as we might require them for solving our problems. Since we are going to look at the computer through the eyes of a computer programming language we therefore need not bother about this internal intricacies anymore. That is the point we have made. So computer processes, computers process very large values by using groups of bytes and typically they will use groups of two bytes, four bytes or eight bytes intrinsically. These are the facilities made available at the hardware level. As I said programming languages are capable of providing many more groupings of this kind. So programming languages permit us to associate names with such groups. Thus names of locations can be assigned larger values. This is the key point. When I say count, when I say m, when I say n tags, when I say price I am not limited by one byte of storage. I can and would declare in my program that this particular name should be associated with so many groups of bytes. Now I will not say it in terms of number of bytes because I don't want to deal with binary numbers, bytes and so on. But this is just for our understanding that such groups of bytes are made available to us for association with any names that we choose. And this is an example, four consecutive bytes together may represent a value ranging from 0 to 2 to the power 32 minus 1. Just as a four digit decimal number can range from 0 to 10 to the power 4 minus 1. The first bit of these bits represent sign and therefore the actual range of integer values that can be represented is this. This by the way is the definition of an integer value inside a C program that we write. Very obviously it means that if we want to store integer values, integer numerical values in some names this is the maximum positive number and this is the maximum negative number. You can just extrapolate from one byte example to four bytes. It doesn't matter how many bytes. An actual internal representation uses two's complement. Now there is a variation. I can have an integer number which just occupies two bytes in which case the range will be minus 32,767 to 3767. Observe that this value is nothing but 2 to the power 15 minus 1 minus 2 to the power 15 minus 1 and plus 2 to the power 15 minus 1. And this is the value which we saw here. The last value numerically will be generally the limit of our integer numbers as we use them inside a C program. So I hope you are generally able to relate what we are going to do in our computer programs to what is likely to be happening inside the computer's hardware. But beyond that it is not necessary for you to understand either the binary number system or the details of the internal representation. Those of you are interested you can actually look it up but that is not very very important. Now we come to the programming language C in C plus plus depending upon the type of values that we want to deal with such groupings has been organized in some meaningful classes or types. So it is not that you can arbitrarily group any number of bytes any type and allocate them to represent your numerical values. There are specific groups which are called classes or which are called types. As a matter of fact int and float the two names that you have seen consistently are two such classes. Consequently any name that we use in our program must be associated with one of these classes. Then only the C plus plus language compiler will be able to allocate not only the memory to that particular name but will know exactly how to deal with that value for addition, subtraction, multiplication whatever you have. Since C plus plus has evolved out of programming language C it retains all the basic data types which are available in C programming language. These are the names of basic data types. CARE. CARE actually is a classical way of representing one character symbol A, B equal to symbol opening bracket whatever each symbol has a value. It so happens that all symbols can be represented by using at most 8 bit code so each character can fit into one byte. Consequently the grouping for the CARE type will be just one byte. We shall not look at the CARE type for now at all. We will look at it later in the class. Int and float are the names that you are familiar with. There is a thing called double and there is a thing called void. Void stands for value less. There is no value. These are the basic types. C plus plus adds two more types one is called bool which is short for boolean and it is used to represent logical values, true and false basically and there is a very artificially created type called wcar underscore t. Now all these names I am listing just for the sake of completeness. We are not going to do anything with these names for quite some time at the moment we will look at only intent float because for most computational problems these two types suffice. Int type is used to represent integer numbers and float type is generally used to represent fractional numbers. It is also used to represent very large numbers as we shall see in a moment. So first of all numerical values, how do we write numerical values? So we write numerical values in some standard way. For example we would write 25, 1, 2, 4, 0, 0, 0, 0, 0, minus 7, 3, 8, 9. Fractional numbers would be written something like this 87.669, 3.14159 you recognize this as value of pi or close approximation minus 0.0000123 if we have very large or very small values it would be very cumbersome to represent them numerically in this fashion either as a fraction. Suppose I have a value which has significant digits in the fraction only in 23rd and 24th place then the way I will have to write it will be 0.0000000 something something and then say 7, 8, whatever. Now everybody who is looking at that value cannot really figure out how many zeros are there unless you painfully count each one. Exactly the same thing will happen when you want to represent very large numbers. So consequently all of us at least in our science and engineering computational problems we use an exponential notation. All of you are familiar with this notation? So 1.24 E9 means 1.24 into 10 to the power 9 minus 1.23 E minus 5 means minus 1.23 10 to the power minus 5 etc. This is a short notation. Observe that this notation has two components one is called the mantissa and the other is called the exponent. Exponent is an integer number which represents power of 10 to be multiplied by the fractional number that we have written here. Since this is how we write numbers in our computational problems C++ permits us to write such constant values in our programs. C++ also accepts such values as important. Consequently we shall continue to use this representation in all of our dealing with the computer. But we know that internally the machine must be using some other representation. For example we know that integer numbers will be converted to binary numbers and depending upon the number of bytes that we use for a particular value the range would get limited automatically. It is then our responsibility to ensure that the values which we either give as input or values which are computed during the process of execution of our program do not exceed the range because if it exceeds the range you will obviously get some wrong value. Further we also note that in any kind of grouping that is permitted if I have to represent such large or small values then internally also there must be a representation which will represent mantissa separately and exponent separately. So whatever be the number of bytes allocated to represent such numbers a few bits must be reserved to store mantissa. So we just note this much and we go further. Declarations in our program first of all any name that we use to represent values the class or type of that value must be declared and consequently that becomes the class or type of a name. Once we declare a name say n count or n tanks to be associated with class of integer numbers we can never put any other type of value in that location. That is how C++ maintains strict type checking that is how C++ knows exactly what computations to be applied to the values inside. Once we associate a name compiler is able to allocate appropriate memory based on that type. For example int, i, j, count, number of tanks, float, x, y, val, radius, circle, underscore, area these are all names we shall see the rules for the name in a moment but what it means is that the name number of tanks would never ever be able to contain a fractional value it will only contain integer value. Similarly the name radius will never ever have an internal representation of a value which is in the integer form it will always have an internal representation which is the equivalent of fractional or exponential notation we shall see briefly how that notation is but it will always have a mantissa and exponent allocated to it. Consequently suppose I give a input value for radius as say 5 5 meters could very well be the radius of a large star now this 5 for me is an integer number but when it goes in through my scene statement and it has to be put inside the location for radius then it will have to be appropriately converted to an internal representation of a real number for us it will effectively become 5.0 because 5.0 is notionally a real number in C programming language 5 is an integer. This conversion is handled automatically by the machine. There is a variation called double which is like a long float so the float word means real numbers which I see in a moment why we call it a float but both int and float ordinarily have 4 bytes associated with these types. 4 bytes will mean 2 to the power minus 2 to the power 31 minus 1 to plus to the power 31 minus 1. In case of float the limits are different and we shall see that in a moment but it is obvious that float means real numbers and therefore the internal representation must be using some kind of an exponent and mantissa mechanism. It cannot use a fractional number with decimal point here or there because then it can't represent larger small numbers and it can't have two different representations one for very large or very small numbers and the other for ordinary fractions so it uses exactly one representation which actually has mantissa and exponent. So obviously if I have 32 bits available to me I might let's say allocate 8 bits to exponent and 24 bits to mantissa. So that means the precision with which my mantissa can be represented is limited by the capacity of 24 bits. If I want larger precision and all larger exponent I might want more number of bytes. This double which is like a long float permits me to use 8 bytes of internal storage. There are other qualifiers to the int type. For example I can say short int which allocates 2 bytes and consequently the limits shown on the previous slide are valid there unsigned which has no sign bet. So value will be from 0 to 2 to the power 32 minus 1. Long which could be either 4 or 8 bytes. On larger machines it is 8 bytes. On the machines that we all use the C++ compiler allocates 4 bytes even to a long int. So long int and int are exactly the same. As I said there exists a type cap which is one byte which stores what we call the ASCII codes. ASCII stands for all of you know that 5. Actually it's a 7 bit code you don't require 8 bits but if you use all 8 bits then you can represent variety of characters called control characters escape characters and so on. Anyway the bottom line is this literally the bottom line. We will not currently use any of these additional types. We will concentrate only on int and float. Before going further let me comment on the float. Consider this value 1.2 e20 very obviously 1.2 is mantissa and 20 is the exponent. We will not look at the binary representation we will just continue the discussion on the decimal numbers. Now imagine this is the memory location inside. As I said for this type of value which is termed as float by the C++ compiler we just consider it to be any real number. It has two components mantissa and exponent. So internally the machine must be reserving some portion to store exponent and some portion to store mantissa. Obviously the larger portion will go for mantissa because that is where we want to keep most of our significant digits of the number. So this number would be represented as plus 1.2 and plus 20 because this is a positive mantissa this is a positive exponent. Note that this number can also be written as plus 1 2 0 0 10 to the power 18. You agree that both are the same numbers? Right. This can also be written as 0.00120 plus 21. You agree that this is right? What should be the correct number then? 0.00120 into 10 to the power 23. So I should correct this to 23. Now which of these representation should actually be used? First or second or third. What is wrong with this representation? What is wrong with this representation is that if I have a limited number of digits in mantissa then by wasting so many digits to just store 0s I will have less space to store non-zero digits of my mantissa. So for example if I have a 6 digit precision which incidentally is the typical precision guaranteed by C++ compiler for flow type of values and if I waste all of those 6 in 0s I can keep shifting decimal point as I wish and I can keep augmenting this but at the end I will have 0 multiplied by 10 to the power 40 or something which is meaningless. So consequently I must utilize every digit position in mantissa to represent something significant. Since I can represent mantissa in any one of these forms my decimal point appears to be moving here, here, here that is the reason why it is called a floating point because I can permit the point to float and have different representations for the same value. Traditionally it has been called float for this reason although it is very cumbersome notation. What actually a machine does is it always normalizes these and in the normalized form it will always remove all these 0s at the beginning and will assume the decimal point to be here. No actual decimal point is stored at all, it is not necessary because the machine knows internally that whatever is the mantissa portion is actually equivalent to point that much value. So no point needs to be stored, no computer storage needs to be wasted for storing a decimal point actually. Consequently both mantissa and exponent are integer numbers as stored internally but the first integer number representing mantissa is taken to be a pure fraction starting with 0 point whatever and it is always normalized in the sense that the most significant digit of the mantissa is always non-zero unless the value itself is zero complete. This is how internally things are represented, whether binary or decimal it doesn't matter, it matters actually in the sense that 1 by 10 or point 1 and the binary point 1 are not exactly convertible and therefore there is always an approximation when you convert a decimal fraction as you deal with it into a binary fraction as the machine deals with it. So that's a problem with the floating point representation but that error is not much when you are talking about larger value. However the precision is limited by this. You can also see that if I allocate 4 bytes typically I would reserve 1 byte for exponent and 1 byte for mantissa and out of that 1 byte for exponent 1 bit at least has to go for psi at both places. But if I have 64 bits then I could reserve a larger value maybe 2 bytes for exponent and maybe 6 bytes for mantissa. Consequently what comes out as a 6 digit procedure for ordinary float variables if I use double I may get as much as 14 or 15 digits of precision but the precision is limited is what I wanted to showcase. We now come to the names. Names are also called identifiers in C++ because they are names not only of memory locations they are also names of other components of the programming language for example IOS stream is a name STD is a name using name space STD what we say is a name. There will be several such names which are called external names because somebody else has defined them for us. We may be using later on many functions in our program and each of those functions would have to be given a name as we shall see so names are important all such names are called identifiers. As far as we are concerned we mostly use identifiers now to represent memory locations where values will be kept as we saw in float or whatever. These are the rules for making the names. A name must begin with a later or a underscore and can contain later digits and underscore so no fancy symbols can constitute a name in C. The name ordinarily for us must begin with a later although technically it can begin with an underscore it is a bad practice to begin a name with underscore. In fact there is a convention which says that the internal compiler names which compiler uses for its own internal variables and internal routines etc always start with one underscore that ensures that your names and the compiler names don't clash. The operating system on the other hand would use routines which would be named underscore underscore so two underscores are typically reserved for that kind of systems of it. Our names without any loss of capability of naming will start with a later. Names can be any long but amongst all the names that you have used first 31 symbols must be unique. So consequently n count used once cannot be used again to mean something else. Please note that the names are case sensitive. So count written in small case, count written in large case, count written in C capital OUNT small these are all different names. So C programming language is case sensitive. Consequently I should be careful about the way I type a name in declaration. I must use it exactly the same way wherever I tend to use it. And of course meaningful names must be chosen by us. Now we come to the integer values. The integer values as we write them in our program must begin with a non-zero digit except when the value is 0. Why is this rule? So this 0 is alright but this 5 I cannot write as 0 5 or 0 0 5. This 253 I cannot write as 0 253 or 0 0 253. Please note that for us the values are same. Why is this rule? Because C programming language also permits us to write numbers in octal and hexadecimal which are two other number systems for base 8 and base 10. All octal numbers begin with a 0. That is the reason why 0 4 5 is not a decimal 45. If I write this as a value in my program or if I give this as an input it would be taken to mean an octal number. So this will be effectively 5 x 8 to the power 0 plus 4 x 8 to the power 1. Similarly hexadecimal numbers those who are interested in the notion of base 16 number system would recognize that if I have base 16 then I need 16 different symbols to represent the value. Now 0 to 9 are common symbols which are used in any number system but I need additional 6. So consequently latest A B C D E and F are used as additional symbols which respectively represent the value 10 11 12 13 14 and 15. After 15 hexadecimal symbols end and you start with 0 again. Hexadecimal numbers would be given as input by us or could be written in our program as proper values with 0 x. The latest A B C D E F wherever they are required to be used so it is perfectly alright to write either a capital letter or a small letter when describing an hexadecimal value. Again we shall for most of our course we shall be not using octal or hexadecimal numbers at all this is included here just for the sake of completeness we shall be using decimal numbers throughout. Floating point values whenever we write a value like this or whenever we write a value like this in our program it will be internally converted to a floating point representation. Whenever we give value like this as input it will be converted to an internal mantissa exponent notation. Whenever we say C out with some float value if the value is representable as a normal fractional value or integer plus fraction it will be given to us in that form otherwise it will be given to us in an exponential notation format that we are familiar with. Why I emphasize this? This is once again to alley the fears that binary number system, hexadecimal number system floating point binary representation, 2's complement etc. Do I need to understand them? Absolutely not. If you are interested go ahead and study them. But as far as C++ is concerned it permits us to use our familiar decimal numbers to and through so we don't have to worry about it. But what we have to worry about are the implications of the range of values that can be represented. For example a real number can have typically a mantissa precision of 6 digits. This is prescribed as minimum by the C programming standard. The actual precision will depend upon the implementation. Exponent range is defined as minus 37 to plus 37 minimum the actual range is more. Whenever you are using a C++ compiler here you use GCC so every compiler has a special information about what are the limits on values for that compiler. So if you take the same C++ program compile it in some other environment on some other computer you might find a different range. Typically if you write your program such that they all work with the minimal range guaranteed then your programs will run perfectly anywhere in the world. All floating point values in our programs of course are decimal or base 10 values. Now we look at the assignment operation. This you are familiar with. If I declare in time that means a storage of 4 bytes is allocated to M and it has a certain range. When I say M is equal to minus 35 the value is assigned to M. So equal to symbol is called assignment operator please note the word operator. In fact as we shall see later on this is exactly like any other operator plus minus star etc etc but this operation does not perform any arithmetic this operation takes the value on the right hand side and stores it in the location designated by the left hand side. So this is actually an assignment operation. I can have an expression so just as I can say N equal to 3, M is equal to 35 star N minus 167. This is perfectly valid. The RHS need not be a single value in an assignment operation. It can be an expression which gets evaluated. Now the point of this particular thing as I have stated again and again because there could be some confusion in the minds of people who are generally used to writing equations in this form. So this is an assignment operator. All that it means is that on the right hand side whether there is a single value or there is an expression if there is an expression the expression is evaluated and the resulting value is called the value of the expression and it is that value which gets assigned to M which gets put into that location. So imagine the expression being computed dumber than taking that value and putting it in that location it will destroy the original contents of the location. There could be conversion of types of values that could happen during assignment. Consider this. I and J are declared integers. Y is declared as floating point. I is equal to minus 25. This is perfectly fine. Integer value is being assigned. X is equal to 2.147. So X and Y are declared float. So these two assignments are straightforward. The right hand side value here is a floating point value and it will be stored in the location for X. I say J equal to 3.2. Now J is an integer number. 3.2 is a floating point value. Floating point value cannot be stored. So floating point value will be converted to integer here. Consequently there will be a loss of procedure. In fact this loss is very clearly defined in C++ as absolute truncation of the fractional part. So consequently the value that will get assigned to J is just 3. Please note that even if I write J equal to 3.8 I would expect a rounding off to happen and the value 4 to be assigned that does not happen. Fraction is mercilessly truncated. Only the integer part is kept there. Consider writing this. J is equal to 1.24 E30. What will be the value of J? Y1. Now this is a mistake. If I had written J is equal to 1.24 J would have become 1. But this is not 1.24. This is actually 1, 2, 4, 0, 0, 0, 0, 0, 0, 0, whatever. It is actually an integer number. But it is stored internally in floating point. Now when that floating point number is converted to integer it becomes so large that it cannot be accommodated in J at all. There is complete loss of precision on conversion. Value is too large. Most of the language compilers will stuff the location for J with the maximum value that is represented. The point is you will not get an error when this statement is executed. But you will get all wrong results. The point to be noted here is that while I can worry about what exactly happens to J I can ask a good quiz question. So study the language compiler and find out what it happens. What happens here? Is that question meaningful at all? It's like saying that after death I will either go to heaven or hell. And after I am dead you argue whether Phatak has gone to heaven or hell. There will be a lot of logical arguments. But the more important thing is for Phatak to live. Once somebody is dead doing post-mortem is no use. In computational problems it is absolutely no use wondering what would happen if the range is crossed. The right thing for us as professionals is to ensure that the range is never crossed. And if the range is crossed something terrible would happen. In fact if you are more unlucky something tangible may happen. Please note my words carefully. If you are very unlucky then something which is seemingly correct may happen but that will be wrong. And you won't even be able to notice because that number looks so reasonable. Only when something is very unreasonable you know something has gone wrong. So this is actually a godsend gift if some such thing happens because you will suddenly see J to be completely meaningless. The moral of the story is please ensure that when you write your assignments, when you write your expressions be careful about the conversations that will happen and be careful to ensure that the numbers remain within range. You will get it with some practice. Take y equal to 29. No problems the value is converted to float which is equivalent to 2.9e1 or 0.29e2 whichever way you want to write it. y is equal to 1, 2, 3, 4, 5, 6, 7, 8, 9. This value is converted to float because the value is repentable as float. However the float has generally 6 digits of precision. So the value may become 1.2357e8. Notice that 1, 2, 3, 4, 5 are the 5 digits. If it has to take the 6 digit instead of taking it as 6 it is taking it as 7. Obviously rounding up has happened. So please note the difference between this and a float to int conversion. And int to float conversion will try to retain a value which is closest to the original value. So if it is something 0.5 or more it will become the next precision and next value in that mantissa otherwise the lower value. We look at more details of an expression which can contain multiple operands which are connected with one or more operators. So a plus b 2 star c plus a slash b m percent n this percent is called modulo operator and it connects two operands which are both integer. Now when this operation is carried out the resulting value replaces this part of the expression. So consequently in this expression the whole expression is never evaluated at one time. One operation at a time. If one operation at a time is to be done then in what order should I evaluate the expression? So there are rigid rules of the language which we shall see. However during the expression evaluation the possible problem is that the two participating values say a and b can be individually within the specified range. But a plus b may go out of the range. This will typically happen when you say a star b multiply two large values. It is your responsibility as programmers to ensure that such transgression does not happen. Because if that happens the result will be erroneous. Here are the arithmetic operators minus plus star slash percent. You know this as multiplication you know slash as division. Percent is a modulo operator it gives remainder. So ten modulo three is how much? One. So it is obviously 2.7 modulo 1.3 has no meaning. So the modulo operator must be used when both sides are integer. If they are not integer they will be converted into integer and then the operation will be carried out. There are precedence rules. Multiplication, division and modulo have higher precedence than minus and plus. So consequently if I have an expression which says a plus b star c, b star c is calculated first because star has a higher precedence than minus. And then result is added to it. Within operators of the same precedence there is an associativity rule. So within the same precedence the associativity is left to right. So for example x star y dash z will be evaluated as x multiplied by y first and result is divided by z. This common sense all of you follow this immediately. Now there are special cases where plus and minus can also be used as unary operator. A binary operator operates upon two operands. A unary operator operates only upon one operand. And this one operand this could be written as plus x minus y. Plus x has no significance really and it would be stupid to write plus x anywhere. However minus y has a meaning. This negates the value. Consequently an expression of that type a star minus b is a valid expression. Because unary operators have higher priority than star slash or percent. So what this expression means a star minus b is that minus b is first evaluated which is actually negation of b and the result is multiplied by a. However I would not like such expressions to be written by us. Because c plus plus provides a very powerful mechanism of parenthesis. Pair of parenthesis when enclose any sub expression that overrides all other priorities defined by the land. Consequently if I write a plus b multiplied by x. This will mean a plus b is to be done first and result is to be multiplied by x. This is what permits me to write expression of this type. What would this mean? Yes any guess? If I were to write it algebraically how would I write it? If I have to evaluate this formula for x. The way I will start writing is first is one. So I write one here. Then this is to be divided by this entire thing. So I will write a bracket here. Then I have x here. Then I will write this plus symbol. I have one again. I have to divide it by something. I have to divide it by this entire thing. So I will write another bracket here. I will write x plus one. I will close this bracket for this x plus one. I will close this bracket for this. And that is how my expression will be written. So once you follow the rules of associative between precedence. You can actually write or understand any expression written in this fashion. Over the weekend I will give you some sample examples to try out writing expressions. And next week I will post the answers for them. Conversions will occur during expression evaluation. If both operands are of the same type the result is of that type. But if one of the two operands is integer. Please remember we are only talking about intent float. Both are int result is int. Both are float result is float. Of course the implication on the range or precision loss etc. You have to worry about. But if one is int and one is float the int is converted to float. That is the rule. We are going to look at the assignment statement. The general form of an assignment operation is name equal to expression as you already know. So I can have this entire thing as an expression. Now the whole assignment operation itself is treated as an expression. So it is not just this is an expression. But why equal to this? This entire thing is an expression. What does it mean? Since an expression has a value this whole thing treated as an expression should also have a value. What should be the value of this entire expression? Ordinarily I would think it is the value of the right hand side. Because that is the value which is being assigned to y. Actually the value of this whole thing taken as an expression is the final value which gets allocated to y. So whatever is stored in y becomes the value of this entire expression. And I can use this fact. For example in writing something like this. m is equal to n is equal to p equal to 10. Now I assume that I have declared m and np as integers. Int m and p. So this looks a funny statement. But this makes sense if I realize that the right most part p equal to 10 is the basic assignment. Since that itself is being treated as an expression, the value of that expression is allocated to n. Then n equal to all of this is an expression. The value of that expression becomes allocated to n. So this is the parenthesized form of this exactly expression. So first p equal to 10 will be executed by the machine. For that this expression will be evaluated. This could be complicated expression. This is 10. The value 10 is allocated to p. So the value of this expression is 10. Please note it is 10 not because of the RHS here. But it is 10 because that is the value that is stored in p. Then that value gets allocated to n. That value gets stored in n. All of these are n. So there is no problem. What if they are not all n? So here is a quiz. What will be the values printed out by the following program? So write down these values. I am outputting. There is no input statement. There is a single assignment. m and n are integer. x and y are flow. What will this program print as value of m, value of x, value of n and value of y? Everybody has written down. Shouldn't take more than 15 seconds. 30 seconds. Next week onwards we shall be using clickers to answer these questions. We should be able to quickly think. Anybody who has not yet written the values, raise your hands. Write it. You have written. No, those who have not written. Everybody has written. Wonderful. So what is the value of x? I hope you figure this out. This will be evaluated as y equal to 8.79. y is float and therefore value of y will be 8.79. This 8.79 value of y is assigned to n in the next expression. Now n equal to 8.79 will chop off the fractional part. And n will become 8 because n is declared as integer. Consequently the value of n is printed as 8. And the value of this entire expression n is equal to y equal to 8.79 will be 8 because that is the value last assigned to n. This value gets assigned to x in the next evaluation of expression. This x is float. So the value merely converts from internal integer format to floating point format. We represent it as 8.0. And this value is again assigned to m which is an integer. It becomes 8. Very obviously such a stupid thing should never be done in our program. If I want to initialize variables with some values, the least decency that I can show to C++ compiler is to assign integer variable separately and assign floating point variable separately. Why cause this confusion? So that's the moral of this story. Here is another quiz. What is the value output by this program? Float x, y, avogadro. Avogadro is equal to 6.023E23. Y is equal to 7.3463. And x is equal to y minus 8.6597 plus avogadro. You can imagine that there is a C out statement. Basically what is the value of x is the question. So please do the arithmetic another 30 seconds and write down the result. Have you done all the computations? How exactly the C++ compiler or a Dumbo will evaluate this expression and what will be the value of x? So everybody got it? Can you raise your hands if you have written the final value? Not yet. Nobody has written a value yet. More than 30 seconds are passed. Another 30 seconds. Look at it carefully, evaluate the expressions the way a C++ compiler will evaluate it and then find out what is the value of x. You are finished. Some people have finally got the value. Has everybody got the final value computed? One more. Please raise your hands if you have not written down the value yet. This is confusing. When you are finished there are few hands. People who have not done it there were very few hands. So you have so many sitters on the wall. Fence-sitters means people who are neither willing to say yes nor willing to say no. Come on I say. Have you already written the values? Fine. So what is the final value? It will be the avogadro number itself. You can do this computation of y minus 8.5697. Very painfully you can do one subtraction from 7.3463 and you will get some value. However, when you want to add that value to avogadro you will have to align the decimal points. One number is 6, 0, 2, 3, 0, 0, 0, 0, 0, 0, 0, 23, 0s. This number is very small. So when you align the decimal numbers this number whatever 5, 6 digits will appear in the rightmost corner. And the actual result that you will get those digits will be chopped off when you normalize that mantissa into a 6 digit of procedure. This is an extremely important lesson that most floating point computations are susceptible to such errors. So later on when we look at matrix multiplication, matrix inversion, solution of simultaneous equations we will look at the ways to worry about these things. We will stop now.