Decisions as Statements

Week 3 made decisions inside expressions. Week 5 makes them with if, else, and nesting, the chapter 5 statements, and then puts the whole toolkit to work on the one program every C lab in the country includes: the roots of a quadratic equation. The first two programs are deliberately small so that the shape of the statement is the whole lesson. The third is where the shape earns its keep.

Program 1: Odd or Even, With and Without else

Print NUMBER IS EVEN or NUMBER IS ODD. The lab asks for it twice: once with else, once without, and the comparison is the point.

Algorithm:

  1. Start.
  2. Read the integer n.
  3. If n leaves no remainder on division by 2, print NUMBER IS EVEN.
  4. Otherwise print NUMBER IS ODD.
  5. Stop.

Now the same decision without else. Two independent if statements each test the condition, one for each outcome:

Both print the same thing for every input, and the second one is worse. It evaluates n % 2 twice, and more importantly the two conditions are only exhaustive because you wrote them to be: change the second test to n % 2 == 1 and a negative odd number, whose remainder is -1, matches neither if and prints nothing. else guarantees exactly one branch runs, with no second condition to keep in step with the first. That sentence is the answer to "why use else" in the viva.

Note the test in the with-else version is n % 2 == 0, never n % 2 == 1 for the odd case. Week 1 established that the remainder of a negative number is negative, so -3 % 2 is -1; testing for zero remainder is the only version that is right for every integer.

Program 2: Positive, Negative, or Zero with Nested if

Algorithm:

  1. Start.
  2. Read the integer n.
  3. If n is greater than 0, print NUMBER IS POSITIVE.
  4. Otherwise, if n is less than 0, print NUMBER IS NEGATIVE.
  5. Otherwise, print NUMBER IS ZERO.
  6. Stop.

The inner if sits inside the outer else, so it only runs once positive has been ruled out, which is why its own else can say "zero" without testing for it. This is the nesting the syllabus names, and chapter 5's else if ladder is the same structure with the inner braces removed and the if pulled up onto the else line. Write it nested in the record, since that is what was asked, and know that the ladder is the same program.

Program 3: The Roots of a Quadratic Equation

For ax² + bx + c = 0, the discriminant d = b² − 4ac decides everything: two distinct real roots when d > 0, one repeated root when d = 0, and a pair of complex roots when d < 0. The program has to handle all three, and refuse a = 0, which is not a quadratic at all.

Algorithm:

  1. Start.
  2. Read a, b, and c.
  3. If a is 0, print that this is not a quadratic equation and stop.
  4. Compute d = b × b − 4 × a × c.
  5. If d is greater than 0, the roots are (−b ± √d) / 2a; print both.
  6. Otherwise, if d is 0, the single root is −b / 2a; print it.
  7. Otherwise, the roots are −b / 2a ± (√−d / 2a) i; print the real and imaginary parts.
  8. Stop.

The three test inputs to keep in the record: 1 -5 6 gives 3.00 and 2.00, 1 2 1 gives the repeated root -1.00, and 1 1 1 gives -0.50 + 0.87i and -0.50 - 0.87i. Then 0 2 1 for the refusal.

Two decisions in this program are the ones the lab manual's version gets wrong. The first is the comparison with zero. d is a double, and chapter 3's rule is that floating-point values are never compared with ==: b * b - 4.0 * a * c for coefficients typed as decimals can land at 0.0000000000000002 when the algebra says 0. So the program tests against a tolerance, EPSILON, on both sides: clearly positive, within the tolerance of zero, and otherwise negative. The same tolerance decides whether a is zero. fabs is the absolute value of a double, from <math.h>.

The second is the ladder itself. Three mutually exclusive cases fit an if, else if, else chain exactly, one test per boundary and the last case free, which is the week's nested-if structure again with a real job. Order matters: the positive test comes first so that the equality test only runs on values already known not to be clearly positive.

In the complex branch, the imaginary part is sqrt(-d), the square root of a positive number, and the two roots differ only in the sign between the parts, so the program computes each part once and prints it twice. Dividing by fabs(2.0 * a) rather than 2.0 * a keeps imag positive when a is negative; the roots are the same pair either way, and it stops the output reading + -0.87i. sqrt needs <math.h>, and on your own compiler -lm at the end of the gcc line; the sandbox links it.

Key Takeaways

  • if with else runs exactly one of two branches; two separate if statements only do that if their conditions are kept exhaustive by hand.
  • Test evenness with n % 2 == 0, never n % 2 == 1, because a negative odd number has remainder -1.
  • Nesting an if inside an else narrows the cases one step at a time; the else if ladder is the same structure flattened.
  • The discriminant b² − 4ac sorts a quadratic into distinct, equal, or complex roots; a = 0 is not a quadratic and is refused first.
  • Compare a double with zero through a tolerance using fabs, never with ==.
  • A chain of mutually exclusive cases is an if, else if, else ladder, tested in an order that makes each later test simpler.