CS 2073-001,   Exam 1, Fall 2005
Answers

Directions: Fill in answers on the pages below. Don't spend too much time on any one problem. All questions below ask for a code segment, which does not need to be a complete program. You never need any #include statements, or the main function, but you should declare the variables that you use.
Points for each problem: 1-15, 2-15, 3-15, 4-20, 5-35, 5i-10, 5ii-10, 5iii and iv-15.

  1. Write a single printf statement that will print the value of an integer n and then the square of n in exactly the following form (no matter what the value of n is):

    Answer inserted in red below.

    Problem 1: C source codeSingle run
    #include <stdio.h>
    
    int main() {
       int n;
       for (n = 1; n <= 16; n += 3)
          printf("n: %i, n squared: %i\n", n, n*n);
    }
    
    n: 1, n squared: 1
    n: 4, n squared: 16
    n: 7, n squared: 49
    n: 10, n squared: 100
    n: 13, n squared: 169
    n: 16, n squared: 256
    

  2. Write a segment of code that uses an extended if-else statement to print the proper message based on the value of a variable IQ, using on the following table. [You don't have to read a value for IQ.]

    Two different answers are inserted in red below. The output is the same for each.

    Problem 2: C source codeSeparate runs
    #include <stdio.h>
    int main() {
       int IQ;
       scanf("%i", &IQ);
       if (IQ > 120) printf("High");
       else if (IQ >= 90) printf("Normal");
       else if (IQ >= 0) printf("Low");
       else printf("Invalid");
       printf("\n");
    }
    -----------------------------------------------
    #include <stdio.h>
    int main() {
       int IQ;
       scanf("%i", &IQ);
       if (IQ < 0) printf("Invalid");
       else if (IQ >= 0 && IQ < 90) printf("Low");
       else if (IQ >= 90 && IQ <= 120) printf("Normal");
       else if (IQ > 120) printf("High");
       printf("\n");
    }
    
    121
    High
    
    120
    Normal
    
    90
    Normal
    
    89
    Low
    
    0
    Low
    
    -1
    Invalid
    
    

  3. Write a program segment that will use scanf to read an integer n and then will use a loop to print the integers from 1 to n inclusive, with a blank between each one. Finally print a newline to skip to the next line. Answer inserted in red below.

    Problem 3: C source codeSeparate runs
    #include <stdio.h>
    
    int main() {
       int n, i;
       scanf("%i", &n);
       for (i = 1; i <= n; i++)
          printf("%i ", i);
       printf("\n");
    }
    
    0
    (only a newline printed)
    
    1
    1
    
    2
    1 2
    
    3
    1 2 3
    
    4
    1 2 3 4
    
    5
    1 2 3 4 5
    

  4. Insert code into the C program below so that the program will print the Centigrade temperature corresponding to an input value for the Fahrenheit temperature. You need to supply the prototype and definition of a function ftoc, which takes a double representing Fahrenheit as its input parameter and returns the Centigrade temperature using the formula: C = (5/9)(F - 32). Answer inserted in red below.

    Problem 4: C source codeSeparate runs
    #include <stdio.h>
    /* insert prototype for function ftoc here*/
    double ftoc(double f);
    
    int main() {
       double f, c;
       scanf("%lf", &f);
       c = ftoc(f);
       printf("Fahrenheit: %.2f = Centigrade: %.2f\n", f, c);
    }
    
    /* insert definition of ftoc here */
    double ftoc(double f) {
       return (5.0/9.0) * (f - 32.0);
    }
    
    212
    Fahrenheit: 212.00 = Centigrade: 100.00
    
    104
    Fahrenheit: 104.00 = Centigrade: 40.00
    
    98.6
    Fahrenheit: 98.60 = Centigrade: 37.00
    
    -40
    Fahrenheit: -40.00 = Centigrade: -40.0
    
    32
    Fahrenheit: 32.00 = Centigrade: 0.00
    

  5. In this problem you will use a random number generator like the generator rand_double() that we used in class. Suppose that it returns a uniformly distributed random double between 0.0 and 1.0. (Do not worry about #include statements, or about initializing the RNG with srand.)

    Each answer is given in red below.

    1. Write a segment of code which will use this random number generator and a loop to print 10 random real numbers between 0.0 and 1.0.

      Problem 5 i: C source codeFirst runSecond run
      #include <stdio.h>
      #include <stdlib.h>
      #include <time.h>
      double rand_double();
      
      int main() {
         int i;
         srand((long)time(NULL));
         for (i = 0; i < 10; i++)
            printf("%20.15f\n", rand_double());
      }
      
      double rand_double() {
         return rand()/(double)RAND_MAX;
      }
      
         0.311942531406853
         0.923045916446972
         0.038132391887779
         0.130670174085847
         0.122756679133864
         0.967290503423331
         0.302804329573551
         0.378144093499586
         0.169674427327548
         0.835203382575514
      
         0.304076678726858
         0.400823272951331
         0.089356198017186
         0.612829898303761
         0.069791023651972
         0.881271054447289
         0.424325234919938
         0.857827221442865
         0.844536928853270
         0.767726750936232
      

    2. Write a code segment that will use rand_double() to simulate flipping a coin. Your segment should print out HEADS half the time and TAILS half the time. [Hint: Remember that half the time rand_double() will return a double that is less than 0.5.]

      Problem 5 ii: C source codeSeparate runs
      #include <stdio.h>
      #include <stdlib.h>
      #include <time.h>
      double rand_double();
      
      int main() {
         srand((long)time(NULL));
         if (rand_double() < 0.5) printf("HEADS\n");
         else printf("TAILS\n");
      }
      
      double rand_double() {
         return rand()/(double)RAND_MAX;
      }
      
      HEADS
      HEADS
      TAILS
      HEADS
      TAILS
      HEADS
      TAILS
      HEADS
      HEADS
      TAILS
      

      It is interesting that the following code does not work correctly:

           if (rand_double() < 0.5) printf("HEADS\n");
           else if (rand_double() >= 0.5) printf("TAILS\n");
        

      Let's rewrite it with a final else to see what happens. By rights "XXXXS" shouldn't be printed at all.

           if (rand_double() < 0.5) printf("HEADS\n");
           else if (rand_double() >= 0.5) printf("TAILS\n");
           else printf("XXXXS\n");
        

      Problem 5 ii (wrong): C source codeSeparate runs
      #include <stdio.h>
      #include <stdlib.h>
      #include <time.h>
      double rand_double();
      
      int main() {
         srand((long)time(NULL));
         if (rand_double() < 0.5) printf("HEADS\n");
         else if (rand_double() >= 0.5) printf("TAILS\n");
         else printf("XXXXS\n");
      }
      
      double rand_double() {
         return rand()/(double)RAND_MAX;
      }
      
      HEADS
      HEADS
      XXXXS
      HEADS
      TAILS
      HEADS
      TAILS
      HEADS
      HEADS
      XXXXS
      

      To see what's going on here, let's flip many times and see how many times HEADS, TAILS and XXXXS come up. Why are we getting the answers below?

      Problem 5 ii (wrong): C source codeSeparate runs
      #include <stdio.h>
      #include <stdlib.h>
      #include <time.h>
      double rand_double();
      
      int main() {
         int heads = 0, tails = 0, xxxxs = 0;
         int i;
         srand((long)time(NULL));
         for (i = 0; i < 1000000; i++) {
            if (rand_double() < 0.5) heads++;
            else if (rand_double() >= 0.5) tails++;
            else xxxxs++;
         }
         printf("Heads: %i\n", heads);
         printf("Tails: %i\n", tails);
         printf("xxxxs: %i\n", xxxxs);
      }
      
      double rand_double() {
         return rand()/(double)RAND_MAX;
      }
      
      Heads: 499740
      Tails: 250787
      xxxxs: 249473
      
      Heads: 500692
      Tails: 249735
      xxxxs: 249573
      
      Heads: 500806
      Tails: 249483
      xxxxs: 249711
      
      Heads: 50000554
      Tails: 25002448
      xxxxs: 24996998
      
      Heads: 500025584
      Tails: 249992600
      xxxxs: 249981816
      

    3. Write a segment of code that will use rand_double() to produce two numbers, and put these numbers into variables x and y, where both numbers are uniformly distributed in the range from -0.5 to 0.5. [Hint: Just subtract a constant from the numbers returned by the RNG.] See below.

    4. Put the previous segment into a loop that will repeatedly produce two new numbers x and y and will count those pairs of numbers generated that satisfy the condition x2 + y2 < 0.25. Suppose this count is stored in a variable count. Your segment should repeat for N pairs, where N is 1000, say. After N pairs altogether, the segment should finally print the ratio count/N as a double. (This ratio is a monte-carlo approximation to pi/4.)

      The answer is in red below, with extra code in black and 8 increasingly large runs.

      Problem 5 iii and iv: C source code
      #include <stdio.h>
      #include <stdlib.h>
      #include <time.h>
      #include <math.h>
      #define N 1000
      double rand_double();
      
      int main() {
         double x, y;
         int i, count = 0;
         srand((long)time(NULL));
         for (i = 0; i < N; i++) {
            x = rand_double() - 0.5;
            y = rand_double() - 0.5;
            if (x*x + y*y < 0.25) count++;
         }
         printf("N:         %i\n", N);
         printf("Count:     %i\n", count);
         printf("Ratio    : %0.8f\n", (double)count/N);
         printf("Pi Approx: %0.8f\n", 4.0*(double)count/N);
         printf("Pi Exact : %0.8f\n", 4.0*atan(1.0));
         printf("Error    : %0.8f\n", 4.0*atan(1.0) - (double)count/N);
      }
      
      double rand_double() {
         return rand()/(double)RAND_MAX;
      }
      
      
      Separate Runs
      N:         1000
      Count:     772
      Ratio    : 0.77200000
      Pi Approx: 3.08800000
      Pi Exact : 3.14159265
      Error    : 0.05359265
      
      N:         10000
      Count:     7853
      Ratio    : 0.78530000
      Pi Approx: 3.14120000
      Pi Exact : 3.14159265
      Error    : 0.00039265
      
      N:         100000
      Count:     78573
      Ratio    : 0.78573000
      Pi Approx: 3.14292000
      Pi Exact : 3.14159265
      Error    :-0.00132735
      
      N:         1000000
      Count:     785150
      Ratio    : 0.78515000
      Pi Approx: 3.14060000
      Pi Exact : 3.14159265
      Error    : 0.00099265
      
      N:         10000000
      Count:     7853602
      Ratio    : 0.78536020
      Pi Approx: 3.14144080
      Pi Exact : 3.14159265
      Error    : 0.00015185
      
      N:         100000000
      Count:     78541857
      Ratio    : 0.78541857
      Pi Approx: 3.14167428
      Pi Exact : 3.14159265
      Error    :-0.00008163
      
      N:         1000000000
      Count:     785407434
      Ratio    : 0.78540743
      Pi Approx: 3.14162974
      Pi Exact : 3.14159265
      Error    :-0.00003709
      
      N:         1000000000
      Count:     785346724
      Ratio    : 0.78534672
      Pi Approx: 3.14138690
      Pi Exact : 3.14159265
      Error    : 0.00020575
      

      This simulation is just comparing the area of the square below (which is 1) with the area of the circle inside (which is pi*r2 = pi*(0.5)2 = pi/4 = 0.785398163). Thus points are chosen at random from the whole square, but only those inside the circle are "counted", and the result is to approximate the value of pi/4.

      Another way to think about this example is to consider a function f defined for two variables x and y, where we must have -0.5 < x < 0.5 and -0.5 < y < 0.5:

        
        z = f(x, y) = 1, if x2 + y2 < 0.5
        z = f(x, y) = 0, if x2 + y2 > 0.5
        

      Then the program computes an approximation to the integral of f over the region specified by the valid values of x and y. In other words, it is the volume trapped underneath the "surface" z = f(x, y). This same method would work for any such function, even one for which the exact calculation was hard or impossible.