Post on 17-Jan-2016
Controlling statement execution
CS101 2012.1
CS101 2012.1
Statement block A block looks like{statement;statement;…statement;}
0 or 1 statement allowed for uniformity Walk down the list executing one statement
after another Effect of each
statement onmemory completesbefore next executed
Note on scope: Outside {…} cannot use variables declared inside
float x = 5, y = 11;float temporary = x;x = y;y = temporary;
CS101 2012.1
If-then-else Store in variable b the
absolute value of variable a
Store in variable c the smaller of the values of variables a and b
Else part is optional Cascades/nests allowed Statement blocks also
optional but best used
int a, b;cin >> a;if (a >= 0) { b = a;}else { b = -a;}
int a, b, c;cin >> a >> b;if (a < b) { c = a;}else { c = b;}
CS101 2012.1
Example: withdrawing money from bankcin >> deduct;if (deduct > balance) { cout << “Account overdrawn\n”;}else { cout << “Successfully withdrawing ” << deduct << endl;
balance -= deduct; // emit paper money}
CS101 2012.1
Curly brackets You can also write then or else parts without
curly brackets, but this could be dangerous Best to always use curly brackets even if not
needed
int m = 5;int n = 10;if (m >= n) ++m; ++n;cout << "m=" << m << "n=" << n << endl;
Increment of n happens outside the if-then action, which only
increments m
CS101 2012.1
Conditional expression Format: cond ? ifExpr : elseExpr Earlier examples rewritten
• b = (a > 0)? a : -a;• c = (a < b)? a : b;
If in doubt, use (parens) to make sure expression tree is correct
Nesting quickly gives unreadable code:(a > 0)? a : ((-a < b)? 100+c : c-100)
CS101 2012.1
Switch statement if (cond1) {…} else if (cond2) {…} else if (cond3) {…} can get tiring
Common use is to choose between different statements depending on the value of a variable
switch (dayOfWeek) {case 0: cout << “Sunday”; break;case 6: cout << “Saturday”; break;default: cout << “Weekday”;}
Can be char, int, long
intIf no break here,
control will “fall through” to the
next case
If none of the listed cases match dayOfWeek
CS101 2012.1
Switch mysteryint val = 5;switch (val) { case 5: cout << "five\n"; // suppose we forget this break; case 4: cout << "four\n"; break; default: cout << "default\n";}
This statement will be executed even though val
is not 4
CS101 2012.1
Switch exampleswitch (ch) {case 'a': case 'A':case 'e': case 'E':case 'i': case 'I':case 'o': case 'O':case 'u': case 'U': cout << ch << " is a vowel" << endl; break;default: cout << ch << " is not a vowel" << endl;
}
Can use fall-through as a feature to
combine many cases
CS101 2012.1
Another switch examplecout << "Enter simple expression: ";int left;int right;char operator;cin >> left >> operator >> right;cout << left << " " << operator << " " << right << " = ";switch (operator) {case '+' : cout << left + right << endl; break;case '-' : cout << left - right << endl; break;case '*' : cout << left * right << endl; break;case '/' : cout << left / right << endl; break;default: cout << "Illegal operation" << endl;
}
CS101 2012.1
The infinite loopwhile (true) { cout << “I will lecture clearly and slowly\n”;
cout << “I will remain quiet in class\n”;}
Insanity: doing the same thing over and over again and expecting different results.
Albert Einstein
CS101 2012.1
Are inputs in increasing order? Keep reading input number for ever, and check if it
is greater than the previous number read
#include <iostream>#include <limits>using namespace std;double prev = numeric_limits<double>::min();while (true) { double cur; cin >> cur; if (cur <= prev) { cout << “Not in increasing order\n”; } prev = cur;}
How do we get out of the infinite
loop?
CS101 2012.1
Printing an integer in binary Surprisingly, standard C++ does not offer a
library function But simple enough For brevity consider printing a byte num Take bit pattern mask = 10000000 Bitwise and: num & mask If result is nonzero, print ‘1’ else ‘0’ Shift mask right to 01000000, then
00100000, 00010000, etc.
CS101 2012.1
Shortcut Instead of shifting mask right, shift num left Use fixed mask of 10000000 Say num = 01101011 = 107 (decimal) 10000000 & 01101011 print ‘0’ Shift num left to 11010110 10000000 & 11010110 print ‘1’ Shift num left to 10101100 10000000 & 10101100 print ‘1’ And so on
CS101 2012.1
Raising a number to an integer power Given a double base and a non-negative integer
power int pow Find basepow
A simple and a more efficient version
double ans = 1;int todo = pow;while (todo > 0) { ans = ans * base; // or ans *= base; --todo;}
CS101 2012.1
Loop invariant Initially, ans=1 and todo=pow After each iteration, ans * basetodo = basepow
• ans multiplied by base, todo reduced by 1
Finally, todo=0, therefore ans = basepow
Number of multiplications: pow
double ans = 1;int todo = pow;while (todo > 0) { ans = ans * base; // or ans *= base; --todo;}
CS101 2012.1
The squaring method Suppose pow = 32 Instead of base*base*…*base
(31 multiplications), run the following
double b2 = base * base;double b4 = b2 * b2;double b8 = b4 * b4;double b16 = b8 * b8;double ans = b16 * b16;// only 5 multiplications
CS101 2012.1
General powers Suppose pow = 29 is a byte Express as 1 + 4 + 8 + 16 Answer is base * b4 * b8 * b16
Let bx take values 0 through 7 Keep squaring base as before If the bxth bit of pow is 1, include the power of
base in the product, else not Already know how to get bit by (val & 1)
0 0 0 1 1 1 0 1
bx
CS101 2012.1
Faster code
unsigned int todo = pow;double ans = 1, term = base;while (todo > 0) { if (todo & 1 == 1) { ans *= term; } term = (term * term); // squaring
todo = (todo >> 1);}
Exercise: Work out the loop invariant
What if pow is a real number?
CS101 2012.1
Factorial
long long int double fac = 1, n;cin >> n;while (n > 0.5) { fac *= (n--);}cout << fac << endl;
Can easily overflow even for moderate n Even if we use double
CS101 2012.1
float x;cin >> x;int numDivs = 0;while (x > 1) { x = x / 10; numDivs = numDivs + 1;}cout << numDivs;
Iteration: Approximating the logarithm How many times must we divide a number x by 10
until the result goes below 1? while (condition) statementOrBlock
Another shorthand:x /= 10;
More shorthands:numDivs += 1;
or++numDivs;
Prolog
Loopbody
Epilog
CS101 2012.1
Quick review Why do we care about how data types are
represented in RAM? To understand the limits of what can be
represented within hardware limitations Thus write more reliable and robust code Can give insights for better algorithms E.g., bit shifts squaring trick fast power
algorithm
CS101 2012.1
Perimeter of regular polygons Polygons inscribed in circle of
radius ½ First, a polygon with sides x Next double the number of
sides, each side is y
Let’s start with x = ½ (six sides)
CS101 2012.1
Code
double sides = 6, x = .5;while (true) { cout << (sides * x) << endl; double a = sqrt(1-x*x) / 2; double b = .5 – a; double y = sqrt(x*x/4 + b*b); x = y; sides *= 2;}
CS101 2012.1
Numerical integration Divide x-axis into
intervals of width h Approximate area under
function f(x) between x and x+h as h f(x)
As h becomes smaller, estimate should become more accurate
But remember finite precision limitations
CS101 2012.1
One loop nested in anotherdouble h = .01;while (true) { double area = 0, x = -1.; while (x + h <= 1.) { area += h * sqrt(1. – x*x); x += h; } cout << 2.*area << endl; h /= 2.; // halve interval width}
CS101 2012.1
Moral of the story On an ideal computer, increasing
number of polygon sides, or decreasing interval width h without bound should get you better and better estimates
Finite precision prevents this (This is why we need to know our
hardware representation!) In general limits are troublesome to
evaluate reliably Luckily there are other methods,
e.g., convergent series
CS101 2012.1
ex
Well-known series
double ans=1, base=x, fac=1, ix=1;bool keepGoing = true;while (keepGoing) { ans += base/fac; base *= x; fac *= (++ix); if (base/fac < epsilon) { keepGoing = false; }}
Tedious to have to exit from a loop
like this
CS101 2012.1
breakwhile (true) { ans += base/fac; base *= x; fac *= (++ix); if (base/fac < epsilon) { break; } cout << (base/fac) << endl;}
Terminates immediately enclosing while loop
CS101 2012.1
Pep Why are we developing algorithms to
compute powers of numbers or or ex if we already have library functions?
Techniques like limits, numerical integration, series summing are universal
Familiarizes us with loop and break constructs
CS101 2012.1
A counting problem Input is int len How many sequences of len bits are there?
• 2len
Of these, how many do not have two consecutive zeros?
If len = 1, answer is 2 (0, 1) If len = 2, answer is 3 (01, 10, 11) Suppose a(len) sequences end with 0 And b(len) sequences end with 1 Required answer is a(len) + b(len)
CS101 2012.1
Counting problem, continued If a sequence ends with 0, second last bit
must be 1 Therefore a(len) = b(len-1) If a sequence ends with 1, second last bit
could be either 0 or 1 b(len) = a(len-1)+b(len-1) Therefore b(len) = b(len-2)+b(len-1) First focus only on b(len) Hemachandra numbers, Fibonacci series
CS101 2012.1
Base cases for b() b(1) = 1 (the bit sequence 1) b(2) = 2 (sequences 01, 11)
int len;cin >> len;if (len == 1 || len == 2) { cout << “b(" << len << ")=" << len;
}else { … }
CS101 2012.1
After base cases Note that b(len) depends only on b(len-1) and
b(len-2) Enough to keep around last two values Rather than all of b(1), b(2), …, b(len)
1 2 3 5
lx
bLxbLxM1bLxM2
1 2 3 5 8
lx
bLxbLxM1bLxM2
CS101 2012.1
Else… len 3int bLxM2=1, bLxM1=2;int lx = 3;while (lx < len) { int bLx = bLxM2 + bLxM1; // shift forward one step ++lx; bLxM2 = bLxM1; bLxM1 = bLx;}cout << len << " " << (bLxM2+bLxM1) <<endl;
Invariant:bLxM2+bLxM1 = b(lx)
CS101 2012.1
Running average The user inputs a sequence of numbers After the third number is input, and for every
subsequent input, print the three-point running average
double a1, a2, a3;cin >> a1 >> a2 >> a3;while (true) { cout << (a1 + a2 + a3) / 3.; a1 = a2; a2 = a3; cin >> a3;}
CS101 2012.1
Migrations between Mumbai and Pune Initial populations m and p Every year, 1/4th of Mumbai migrates to Pune And ½ of Pune migrates to Mumbai Simulate for k years Do the populations stabilize?
CS101 2012.1
Migrations codemain() { double m, p; int k; cin >> m >> p >> k; for (int t=0; t<k; ++t) { p = p – p/2. + m/4.; m = m – m/4. + p/2.; // print }}
Synchronous vs. asynchronous update
CS101 2012.1
Greatest common divisor (gcd) Given integers m n 1, find their gcd gcd(m,n) = gcd(n, m%n)
int m, n;cin >> m >> n;// assume m >= n
while (n > 0) { const int tmp = n; n = m % n; m = tmp;}cout << m << endl;
Let h = gcd(m,n) h divides m, nLet m = n*q + rGiven h divides n …… h must divide r h divides gcd(n,r)(so h gcd(n,r))Also, gcd(n,r) dividesn and r, n and m h gcd(n,r)
CS101 2012.1
“String theory” Iterative computations are demonstrated well
on arrays We have already introduced strings, which are
arrays of characters Luckily the system manages the array space
for us Can assign and append to strings Can read a position: cout << message[px] Can write a position: message[px] = ‘q’ That’s all we need for now
CS101 2012.1
Printing a string in reverse
string message;getline(cin, message);int mx = message.size()-1;while (mx >= 0) { cout << message[mx]; --mx;} mx updated in a completely predictable way Ideal candidate to write as for loop
Character at position mx in
string message
CS101 2012.1
While and for
cond
stmt
t
f
while (cond) { stmt }
cond
stmt
stepper
init
f
t
for (init; cond; stepper) { stmt }
CS101 2012.1
Printing reversed string, for loop General syntax
for (prelude; condition; stepper) { body } Equivalent to
prelude; while (condition) { body; stepper; }
for (int mx = message.size()-1;mx >= 0; --mx) {
cout << message[mx];}
Look, a declaration
In ISO standard C++, mx is no longer available here
CS101 2012.1
Nested for loops Calculate (again!) by… Generate grid of x, y points in the planefor (double x=-radius; x<=radius; ++x) { for (double y=-radius; y<=radius; ++y) { // detect if they are within a circular disk
}}
Just to demonstrate nested for loops• radius2 grid points unacceptably slow• Numerical integration much faster, at least as
accurate
CS101 2012.1
Finding needles in a haystack Given two strings, needles and haystack needles has no repeated characters haystack may repeat characters How many characters in needles appear in
haystack at least once? needles = “bat”, haystack = “tabla” 3 needles = “tab”, haystack = “bottle” 2
CS101 2012.1
One needle in a haystack Subproblem: given one character ch and a
string find if ch appears in string at least once
char ch; // suitably initializedstring haystack; // suitably initializedint ans = 0; // will change to 1 if foundfor (int hx = 0; hx < haystack.size(); ++hx) { if (ch == haystack[hx]) { ++ans; break; // quit on first match }}
CS101 2012.1
Many needles: nested loopmain() { string needles, haystack; getline(cin, needles); getline(cin, haystack); int ans = 0; for (int nx=0; nx < needles.size(); ++nx) { char ch = needles[nx]; for (int hx = 0; hx < haystack.size(); ++hx) {
if (ch == haystack[hx]) { ++ans; break; // quit on first match } } // ends haystack loop } // ends needles loop}
Generalize to work in case needles can also
have repeated characters
CS101 2012.1
Duplicate needles needles = “bat”, haystack = “tabla” 3 needles = “tab”, haystack = “bottle” 2 needles = “bata”, haystack = “tabla” 3 Two approaches
• Dedup needles before executing earlier code (reducing to known problem)
• Dedup needles “on the fly” (inside the nx loop)
Exercise: If the input strings have n and h characters, at most how much time does
the needle-in-haystack search code take?
CS101 2012.1
Parallel steppers Print the first character of a string, then the
last, then second, then second last … until you meet in the middle
for (int lx=0, rx=message.size()-1;lx < rx; ++lx, --rx) {
cout << message[lx] << message[rx];
}
Parallel steppers
Middle character of odd-length
string will not get printed
CS101 2012.1
Reversing a string
for (int lx=0, rx=msg.size()–1;lx < rx; ++lx, --rx) {
const char tmp = msg[lx]; msg[lx] = msg[rx]; msg[rx] = tmp;} H e l l o
lx rx
o e l l H
lx rx
o l l e H
lx,rxUsed in a rhs expression,
msg[lx] is a character value
Used as lhs, msg[rx] is a cell where a character is
to be written
CS101 2012.1
Comparing two strings of equal length For simplicity assume only lowercase chars Remember ‘a’ < ‘b’ < … < ‘y’ < ‘z’ Return difference of first differing character, 0 if none
(identical strings)
string as, bs; // suitably initializedint ans = 0;for (int ix=0, in=as.size(); ix<in; ++ix) { if ( (ans = as[ix] – bs[ix]) != 0) break;}cout << ans;
CS101 2012.1
Generalize to arbitrary lengths “Hello” < “Help” but “Hello” > “Hell” Scan both strings from the beginning If differing character found, same as before If a string ends, it is “less” than the otherint ans=0, ax=0, bx=0, an=as.size(), bn=bs.size();
for (; ans==0 && ax < an && bx < bn; ++ax, ++bx) {
if ( (ans = as[ax] – bs[bx]) != 0) break;}if (ans == 0) { ans = an – bn;}
This results in an arbitrary integer as the return value in case of
unequal input string lengths, but the sign of ans is what is important
CS101 2012.1
break and continue Sometimes, we need to exit from a loop in an
unexpected way Or, in the middle of the loop body, we may
want to abandon that iteration and start on the next iteration
The break and continue statements provide these capabilities
Use sparingly, only in a clean, well-lighted area
CS101 2012.1
Summary If then else, switch, while, for Printing numbers in any radix Raising number to power, squaring trick Factorial, summing convergent series Taking limits, calculating pi Numerical definite integration Computing discrete series recurrences Greatest common divisor Nested loops, string manipulations