Additional Lecture Material 1 Basic C++ types, expressions and statements The primitive types in C++: long double double float These approximate the real numbers, with limitations on both magnitude and precision. Normally, we use the double type, reserving the others for when extra precision or storage conservation is called for. The literals (constant values) of type double includes both fixed point and scientific notations: 3. .003 3.01 3e-2 The operations that produce new doubles from old ones include the standard 4 operations. + - * / These operations have precedence rules that partially determine the order of evaluation. 3. + 4. * 5. produces the value 23, not 60. Parentheses can change the evaluation order, to overcome the standard associativity. (3. + 4.) * 5. produces the value 60. There are also unary operators + and - for doubles: +(60*2) -(3+2*11) For identifiers of type double, there are operators that modify the values associated with those identifiers. x = 3.1 causes the identifier x to be associated with the value 3.1. Likewise, x += 3.1 x -= 3.1 x *= 3.1 x /= 3.1 cause the value of x to be changed by adding 3.1, or subtracting, multiplying by, or dividing by it. The int type represents integers, subject to limitations on range. Literals for the int type include 1 12 -2 0 Note that "1." is not an int; it is a double. You may choose to disambiguate your use of double literals by using "1.0" as an alternative to "1.". The operations on ints include the ones available for doubles. Since the result of any operation must be an integer, the divide operation produces an int, regardless of whether the exact quotient is among the integers. In practice, the exact result is truncated toward zero; in theory, the rounding direction when one or both operands is negative is not defined. An additional operator "%" is available to report the remainder in integer division. 7%3 is 1, for example, and a = (a/b)*b + a%b regardless of how division handles rounding for negative arguments. Besides the operators that produce new values, there are operators that modify existing values, as with doubles. += -= *= /= %= The unsigned type is like the int type, except that: 1. No negative values can be represented. 2. Literals have a 'u' at the end: 1u, 480u. Generally, use unsigneds counters, which cannot have negative values. Both int and unsigned types have modifiers (short, long, long long) to save space or expand representable range. Use them only when space saving or extra range is necessary. The char type represents characters. The literals are 'a', 'A', and so on. Special characters like newlines, tabs, and so on are represented by codes with a backslash: '\n' for newline, '\t' for tab, '\\' for backslash. Some arithmetic is possible and legitimate with chars. The difference between two chars is an int, representing the distance between them in the character set. For example, 'c'-'a' is 2. Likewise, the sum of a char and in int is an int. For example, '0' + 3 is '3', and 'w' + ('A'-'a') is 'W'. The bool type represents truth values. Its two literals are true false Boolean values are also produced as the result of comparing values. The operators == and != compare values of the same type for equality and inequality. It is a common beginners' error to use = instead of == for equality comparison; detection of this error can be made easier if you develop the habit of placing the constant operand, if there is one, first. x + y == z produces the same boolean value as z == x + y but the former, with the operator written incorrectly, does not compile, while the second does something wrong, silently. For ordered comparisons, the operators < <= >= > also produce boolean values, as does the unary operator '!', which performs a test for zeroness. !0 is true !4 is false While the boolean operators & and | presented before are commutative, there are other versions that explicitly evaluate the first operand before the second. z != 0. && a/z < 5. never divides by zero, because if z is zero, the first clause, and thus the whole expression is false. In the same way, z == 0. || a/z >= 5. is true if z == 0, and in that case a/z is not evaluated. Expressions like we've discussed become expression statements when a semicolon is attached. Expression statements are useful only when they change the value associated with an identifier. x = y+3; The statements that associate an identifier like x or nAmts or prev1 with a type are declaration statements. int x; unsigned nAmts; double prev1, prev2; In these examples, the initial values of x and the rest are undefined. Undefined is bad. Better to associate initial values with identifiers, like this int x(0); unsigned nAmts(87); double prev1(52.0), prev2(5.24); or int x = 0; unsigned nAmts = 87; double prev1 = 52.0; double prev2 = 5.24;