Module 8: Applications


Objectives

 

By the end of this module, for simple programs with real numbers, you will be able to:

 

8.0 Audio:
 


8.0    Some math history via programming - example 1

 

In this and the next few sections, we'll use simple for-loops to compute some of the most famous constants in mathematics, and explore a few mathematical ideas (no background needed).

One key idea in mathematics is the notion of a limit:

  • Let x1, x2, ..., xn, ... be a sequence of real numbers.

  • For example:
             x1 = 1
             x2 = 3
             x3 = 5
             x4 = 7
             ... (and so on)
        

  • A limit explores the idea of what the sequences tends towards.

  • The above example grows to (infinity).

  • Example: suppose xn = 1/n.
           ⇒ Then, xn gets closer to 0 as n → ∞. Let's explain:
    • First, let's enter values of n to calculate (with a calculator) a few values:
               x1 = 1/1 = 1
               x2 = 1/2 = 0.5
               x3 = 1/3 = 0.3333
               x4 = 1/4 = 0.25
               x5 = 1/5 = 0.20
               ... (skipping a few) ...
               x10 = 1/10 = 0.1
               ... (skipping a few) ...
               x100 = 1/10 = 0.01
               ... (skipping many) ...
               x10000 = 1/10000 = 0.00001
          
    • Clearly, as n gets larger, xn gets smaller and smaller.

  • We say limn→∞ 1/n = 0.

  • How to say out aloud: "The limit, as n tends to infinity, of the sequence 1/n is zero".

  • Note: our goal in this module is to explore the use of programming in discovering math; we will not test you on math.
 

Next, let's explore some reasoning related to sequences (of numbers):

  • We want to understand what happens to the n-th power of a number as n increases.

  • Consider the number 3/4 and the sequence (3/4)n.

  • In other words we want to explore what the sequence below "is headed towards".
             x1 = 3/4
             x2 = (3/4)2 = 0.5625
             x3 = (3/4)3 = 0.4218 
             x4 = (3/4)4 = 0.3164
             ... (and so on)
        

  • Since (3/4)2 = (3/4) × (3/4), one could say that "three-fourths of 3/4" will be smaller than 3/4.
    This is indeed the case:
             x1 = (3/4) = 0.75
             x2 = (3/4)2 = 0.5625 (less than 0.75)
        

  • Similarly, (3/4)3 = (3/4) × (3/4)2, we'll get an even smaller number that's next in the sequence.
             x1 = (3/4) = 0.75
             x2 = (3/4)2 = 0.5625 
             x3 = (3/4)3 = 0.4218 (less than 0.5625)
        

Let's write a program to verify:

public class TestSequence {

    public static void main (String[] argv)
    {
	// Remember: 3/4 = 0 because it'll be integer division.
	// We need to make this 3.0 / 4.0. 
	double x = 3.0 / 4.0;

	for (int n=2; n<=20; n++) {
	    System.out.println (x);
	    // The next term is 3/4 times the previous.
	    x = (3.0/4.0) * x;
	}
    }

}
    
 

8.1 Exercise: Write up the above program and verify that successive powers of 3/4 are getting smaller. Now try another number that's less than 1, like 0.95 and examine its successive powers.
 

Next, let's look at a number that's larger than 1, like 4/3.

  • Since (4/3)2 = (4/3) × (4/3), one could say that the result will be larger than 4/3.

  • Thus, (4/3)n should get larger.
 

8.2 Exercise: Change the code above to verify. Now try another number that's bigger than 1, like 1.05, and examine its successive powers.
 

We can generalize this:

  • If x is any number (like 3/4), we're interested in what happens with successive powers xn.

  • Note: for simplicity, we'll stick with positive numbers and not deal with powers of negative numbers.

  • By the same reasoning as above, if x is smaller than 1, then xn gets closer and closer to 0.

  • Similarly, if x is larger than 1, then xn grows unboundedly, towards infinity (but not beyond).

  • If x=1, of course, the result is boring: xn=1.

  • To summarize for any number x:
    • If x < 1, the limit is 0.
    • If x > 1, the limit is .
    • If x = 1, the limit is 1.

  • Observe that the limits are rather stark: only three limits.
 

A small tweak will make this more interesting:

  • Suppose x itself is changing from one iteration to another.

  • We'll use the notation xn to denote the value of x at the n-th iteration.

  • For example: at the n-th iteration x could be the n-th odd number:
             x1 = 1
             x2 = 3
             x3 = 5
             x4 = 7
             ... (and so on)
        

  • To print the successive powers, we could use code like:
    	for (int n=1; n<=20; n++) {
                // Compute the n-th odd number:
                double x = 2*n-1;
    
                // Use a for-loop to compute xn
                double power = 1;
                for (int j=1; j<=n; j++) {
                    power = power * x;
                }
    
                System.out.println ("n-th power of xn=" + power);
    	}
        
     

    8.3 Exercise: Write up the above code in OddSequence.java.

  • Clearly, the sequence grows very fast towards infinity.

  • The fact that xn is itself increasing (successive odd numbers) and that we're computing higher powers, combines for a "double acceleration" of sorts.

  • You also see how extremely large numbers are printed using the so-called floating-point notation (with "E").

  • So, now let's take a decreasing sequence and subject that to higher powers to see if they "offset" each other.

  • As the decreasing sequence, we'll pick xn = (1 + 1/n).

  • Here are some terms:
             x1 = 1 + 1/1 = 2
             x2 = 1 + 1/2 = 1.5
             x3 = 1 + 1/3 = 1.333
             x4 = 1 + 1/4 = 1.25
             ... (and so on)
        

  • Clearly, this is a decreasing sequence.

  • We'd like to know what will happen if we raise the successive terms to higher powers:
             (x1)1 = (1 + 1/1)1 = ?
             (x2)2 = (1 + 1/2)2 = ?
             (x3)3 = (1 + 1/3)3 = ?
             (x4)4 = (1 + 1/4)4 = ?
             ... where is this headed?
        

  • Here, even though successive x's are decreasing, we are "powering" them to higher power.

  • So: does this new sequence decrease to zero or grow to infinity?

  • Now let's compute successively higher powers:
    	for (int n=1; n<=20; n++) {
                // Compute the n-th term:
    	    double x = 1.0 + 1.0/n;
    
                // Use a for-loop to compute xn
                double power = 1;
                for (int j=1; j<=n; j++) {
                    power = power * x;
                }
    
                System.out.println ("n-th power of xn=" + power);
    	}
        
 

8.4 Exercise: Edit, compile and execute the program, writing your code in StrangeSequence.java. Try much larger values of n. What does the limit of the sequence appear to be?
 

The limit of the above sequence is the celebrated and important mathematical constant e:

About e:

  • e is approximately 2.718...

  • It is just as important and practical as its better known cousin, π.

  • e turns up all over the place in math and engineering.

  • e, like π, is transcendental.

  • It's unexpectedly interesting that such a simple combination of a decreasing sequence and higher powers results in this very important constant.
 


8.1    Some math history via programming - example 2

 

Now that we've mentioned π, let's look at a sequence that computes it.

  • First, recall: π = ratio of any circle's circumference to it's diameter.

  • Just knowing this doesn't give us a practical way to compute π
    • We could place strings along a circle and its diameter.
    • Then straighten out the first string and estimate the ratio.
    • But this would be quite "low res".

  • In fact, a great deal of effort in earlier civilizations went into estimating π.

  • The first successful effort is attributed to Archimedes in 250 BC who used ... (wait for it) ... a sequence! (Much like we did above).

  • In fact, he used two different sequences. About which more later.

  • His approach withstood centuries of attempts to improve, until the arrival of calculus.

  • We'll use the so-called Gregory-Leibniz series from the post-calculus era:
           π = 4 (1 - 1/3 + 1/5 - 1/7 + 1/9 + ....)

  • Let's do this in steps. First, suppose we had to compute
           1 + 1/3 + 1/5 + 1/7 + 1/9 + ....

  • Some pseudocode:
            sum = 0
    	for i=1 to k {
               sum = sum + 1.0/(2*i-1)
            }
          

  • Next, how do we alternate the sign? Here's one way:
            sum = 0
    	sign = 1
    	for i=1 to k {
               sum = sum + sign/(2*i-1)
    	   sign = -sign;
            }
          

  • Now let's put this all into code to print out the first n terms:

     

    8.5 Exercise: Edit, compile and execute the program. Try larger values of n to see how quickly it converges to π. When k=4 in the outerloop, trace through the execution inside the outerloop in (module8.pdf).

  • There are now more sophisticated sequences that compute π to very high accuracy.

  • The current world record (which does not appear to have any practical use) is about a trillion digits of accuracy.
 

8.6 Video:

 


8.2    Some math history via programming - example 3

 

Let's look at a third famous constant: Φ, the golden ratio.

  • Recall the definition of the Fibonacci sequence: Xn = Xn-1 + Xn-2.

  • The starting values: X0=0, X1 = 1.

  • We wrote a program to print out successive Fibonacci numbers:

  • Consider the sequence Yn = Xn / Xn-1.

  • That is, the ratio of successive Fibonacci terms.
 

8.7 Exercise: In GoldenRatio.java modify the above program to compute this ratio. What does it appear to converge to?
 


8.3    Some math history via programming - example 4

 

Zeno's paradox:

  • Zeno was a Greek philosopher famous for creating several apparent paradoxes.

  • His most famous one: the hare and the tortoise

    • Suppose a hare and tortoise are separated by 1 unit of distance.
    • Suppose hare is twice as fast as tortoise.

  • In the time the hare covers 1 unit, the tortoise has moved foward 1/2 unit.

  • In the time taken to cover this 1/2 unit, the tortoise has moved forward 1/4 unit ... etc.

  • Zeno claimed that by the time the hare catches up, the tortoise will have traveled:
           1/2 + 1/4 + 1/8 + ....
    An infinite sum

  • Zeno's paradox: the hare will never catch up.

  • Let's resolve this by writing a program to compute
           1/2 + 1/4 + 1/8 + ....

  • Such a sum is often called a series:

  • It can be written as a sequence. Define
           Xn = 1/2 + 1/4 + 1/8 + .... + 1/2n
    Then, we are interested in
           limn→∞   Xn

  • Let's write a program to compute this for any n:

  • Note: in the program above, xn is a variable name.
           ⇒ We could just as easily have called it anything else.
     

    8.8 Exercise: What does the series appear to converge to? Write your code in Zeno.java.
     

    8.9 Audio:
     

    Thus, we see that even though a series appears to add up an infinite number of numbers, the resulting sum can be finite. And a small number too.

    This sort of strangeness with respect to numbers befuddled the Greeks and others to follow, until rigorous mathematics in later centuries built a firm theoretical and axiomatic foundation.
     


    8.4    Data analysis

     

    We'll now explore some data analysis with words:

    • Recall from Module 7:
      • We were able to use WordTool. to generate random nouns, verbs and such.
      • We also learned to obtain the length of a string.

    • Let's estimate the average length of a verb and compare that to the same metric for nouns.

    • Generally, we're accustomed to seeing big nouns like: "establishment" and "temperance".

    • Whereas popular verbs can be small, like "read" and "write".

    • We will try and quantify this by getting the average of N random nouns and verbs.
     

    8.10 Exercise: Write code in WordAnalysis.java with a for-loop that calls WordTool.getRandomVerb() and assigns to a String variable. Then, extract its length and accumulate into a variable called total. Continue from there to compute and print the average verb length. Use 1000 such verbs. Then repeat for nouns. You will need to download into the same directory: WordTool.java and wordsWithPOSAndPron.txt. What is the difference between the average lengths? Are other parts of speech shorter or longer on average?
     

    8.11 Audio:
     


    8.5    Functions and plotting data - example 1

     

    Let's start by plotting a simple function:

    • Suppose we want to plot the familiar function f(x) = sin(x) in the range [0,10].

    • Let's start by picking 20 points to plot.

    • We'll divide the interval [0,10] into 20 so that the x values (along the x-axis) are
              0
              0.5
              1.0
              1.5
              ... (20 equally spaced values along x-axis)
              9.5
              10.0
          

    • Pictorially, this is what we've done so far:

    • Then, the y-values are calculated by applying the function:
              f(0)    = sin(0)      =  0 
              f(0.5)  = sin(0.5)    =  0.48
              f(1.0)  = sin(1.0)    = 0.84
              f(1.5)  = sin(1.5)    = 0.997
              ... 
              f(9.5)  = sin(9.5)    = -0.075
              f(10.0) = sin(10.0)   = -0.54
          
    • Let's put this into code:
      	// 20 points along the x-axis
      	int N = 20;
      	double xSpacing = (10.0 - 0.0) / N;
      	for (double x=0; x<=10; x+=xSpacing) {
      	    // Compute f at the x-value of x
      	    double f = Math.sin(x);
      	    // Plot the point x, f(x)
      	    DrawTool.drawPoint (x, f);
      	}
          
     

    8.12 Exercise: Download DrawTool.java and FunctionExample.java Then, compile and execute FunctionExample.java. Edit the file FunctionExample.java to increase to 100 the number of points (N) at which the function is computed - this should produce a smoother curve.
     


    8.6    Functions and plotting data - example 2

     

    Next, let's work with some real data

    • Consider the following data:
      x f(x)
      8.33 1666.67
      22.22 3666.67
      23.61 4833.33
      30.55 5000
      36.81 5166.67
      47.22 8000
      69.44 11333.33
      105.56 19666.67

    • Let's write code to display this data:
      public class FunctionData {
      
          public static void main (String[] argv)
          {
      	DrawTool.display ();
      	DrawTool.setXYRange (0, 110, 0, 20000);
      
      	double x = 8.33; 
      	double f = 1666.67;
      	DrawTool.drawPoint (x,f);
      
      	x = 22.2;  f = 3666.67;
      	DrawTool.drawPoint (x,f);
      
      	x = 23.61;  f = 4833.33;
      	DrawTool.drawPoint (x,f);
      
      	x = 30.55;  f = 5000;
      	DrawTool.drawPoint (x,f);
      
      	x = 36.81;  f = 5166.67;
      	DrawTool.drawPoint (x,f);
      
      	x = 47.22;  f = 8000;
      	DrawTool.drawPoint (x,f);
      
      	x = 69.44;  f = 11333.33;
      	DrawTool.drawPoint (x,f);
      
      	x = 105.56;  f = 19666.67;
      	DrawTool.drawPoint (x,f);
          }
      
      }
           

    • Notice that we had to adjust the default x and y range.
     

    8.13 Exercise: Edit, compile and execute FunctionData.java. Then, try to estimate the slope of a line that would approximately "fit" the points. Use the DrawTool.drawLine method to draw a line with your estimated slope. For example, if your estimated slope is m, you would add this to your program:

        DrawTool.drawLine (0,0, 110, m*110);
      
     

    8.14 Exercise: The data is from a world-changing paper published in 1929. Use a websearch to discover what the data is and why it changed the world.
     

    8.15 Audio:
     


    8.7    Java's Math package

     

    Let's introduce some programming terminology first:

    • A programming language is a collection of reserved words like public, class, int, double, and "grammar" like rules for writing code using both the reserved words, punctuation (like periods, brackets), and your own identifiers>

    • Most languages also come with pre-packaged programs to make it easy to write complex programs.

    • Why? Think about this:
      • Most people need to be able to read and write to files.
      • Many programs need to use math functions.
      • Yet others need to draw, create buttons and menus and such.
      • If a language provided nothing beyond the language, programmers would need to write code repeatedly for all these "basic" needs.

    • So, every language also features a library of useful programs that programmers can use.

    • Some languages like C have small libraries. Others, like Java, have enormous libraries.

    • Often, there are third-party libraries that can be bought because they happen to do something very useful in some application niche.

    • We will later learn how to use libraries in detail.

    • In fact, we've already used the methods inside System (like println).

    • Sometimes people will use the term API interchangeably with library. This is an acronym. The original is a mouthful (Application Programmer Interface), probably created by someone with too much time on their hands.
     

    That said, let's look at one very useful part of Java's library, with math functions. Here's an example:

    public class MathExamples {
    
        public static void main (String[] argv)
        {
    	// Compute the square root of a number:
    	double x = 2;
    	double y = Math.sqrt (2);
    	System.out.println (y);
    
    	// The package has many trig functions, e.g.
    	double angle = 3.14159;
    	double sinOfAngle = Math.sin (angle);
    	System.out.println (sinOfAngle);
    
    	// Power, exponent, logarithm etc, for example:
    	double fourthPowerOf3 = Math.pow (3.0, 4.0);
    	System.out.println (fourthPowerOf3);
    
    	// Generate random numbers between 0 and 1.
    	double randomValue = Math.random ();
    	System.out.println (randomValue);
        }
    
    }
        
    What's important to know:
    • Libraries are NOT meant to be memorized.

    • Something like the Java library is too large for any one person to know completely.

    • When you need something, you browse the library to look for it.

    • It's often useful to learn by looking at examples of using something from the library.
     

    8.16 Exercise: Do a web search for "Java API". The follow the link to merely "check out" the API and get a feel for how impossibly large it is. One the lower-left menu, look for the Math collection and casually browse through the various functions. If you were not able to find the link, use this one.
     

    About the Java library:

    • The link above took you to the standard documentation.

    • It will take us a while to understand how to read it, and to read only those parts that are useful to the task at hand.

    • Some parts of the library need a lot more expertise to understand how to use. There are entire books written for some aspects of the library.
     


    8.8    Using animation for visualization

     

    We will explore the use of visualization for problems in motion:

    • Consider an object (say, car) that's moving at velocity v meters/second.

    • Then, the distance traveled after t units of time is: d = vt meters.

    • Let's not worry about the physics but think "physics tells us how to predict motion; we'll merely use that via their formulas".

    • Similarly, consider a ball that's dropped from a height of 100 meters.

    • The height after t seconds, it turns out, is predicted by the formula: h = 100 - ½gt2.
      (Here, g = 9.8).

    • Let's visualize both using our drawing tool:
      public class MotionExample {
      
          public static void main (String[] argv)
          {
      	DrawTool.display ();
      	DrawTool.setXYRange (0,100, 0,100);
      
      	DrawTool.startAnimationMode ();
      	double v = 10;
      	for (double t=0; t<=10; t+=0.1) {
      	    double d = v*t;
      	    double h = 100 - 0.5*9.8*t*t;
      	    DrawTool.writeTopValue (t);
      	    DrawTool.setPointColor ("blue");
      	    DrawTool.drawPoint (d, 0);
      	    DrawTool.setPointColor ("red");
      	    DrawTool.drawPoint (70, h);
      	    DrawTool.animationPause (100);
      	}
      	DrawTool.endAnimationMode ();
          }
      
      }
           
     

    8.17 Exercise: Edit, compile and execute the above program. Make sure DrawTool.java is in the same directory. Guess at the velocity v needed to create a collision between the two objects by changing v in the program. At what time would this occur?
     


    8.9    Archimedes and π

     

    Now that we can draw, let's go back in time to draw what Archimedes (circa 250BC) drew in his quest to compute π
     

    8.18 Exercise: Download Archimedes.java, compile and run. You already have DrawTool in your directory.
     

    What you see is:

    • A hexagon inscribed in a circle (that is, inside the circle but as large as possible).

    • Some other details like axes, coordinates, and lines from the center of the circle to the hexagon's corners.
     

    Archimedes' idea:

    • Suppose we could compute the perimeter of the hexagon:

      • The perimeter could serve as an approximation of the circle's circumference.
      • Then divide this by the radius (which we already have fixed) to get an approximation of π
      • For the hexagon it turns out to be 3.0.

    • Archimedes reasoned that if he could calculate the perimeter of any polygon inscribed, he could get better approximations.

    • For example, a 10-sided polygon:

      Turns out: this gives π = 3.09

    • A 20-sided polygon would produce an even better approximation.

      Turns out: this gives π = 3.12 (not bad)

    • But once you know how to do this, you can calculate for much larger polygons such as this 100-sided one, which is nearly indistinguishable from the circle to the naked eye:

      Turns out: this gives π = 3.14107 (pretty good)

     

    Now let's examine some of the details (a loop, really):

    • We will not worry about the trigonometry. In fact, it's likely that Archimedes did not either since others had solved problems about triangles before.

    • So, let's start with drawing a circle:
      	// Set DrawTool up so that the circle's
      	// center is at the origin:
      	DrawTool.display ();
      	DrawTool.setXYRange (-10, 10, -10, 10);
      	DrawTool.drawMiddleAxes (true);
      
      	// Radius:
      	double r = 8;
      
      	// Draw the circle
      	DrawTool.drawCircle (0, 0, r);
          
       

      8.19 Exercise: Download ArchimedesSteps.java, compile and run. Then examine the code.

      Note:

      • We have commented out almost everything except the drawing of the circle (because we'll do the rest in steps).
      • DrawTool expects the center's coordinates (0,0) and the radius.

    • Next, we'll let N be the number of sides of the polygon.

    • In a loop that runs N times, we'll draw the triangles and compute the length.
              ...
      
      	// Interior angle of each triangle.
      	double angle = 2*Math.PI / N;
      
      	// Initialize the variable that will accumulate the lengths
      	// of edges that comprise the perimeter.
      
      	double perimeter = 0;
      
      	for (int i=0; i<N; i++) {
      	    // One corner of the triangle on the circumference:
      	    double x1 = r * Math.cos (i*angle);
      	    double y1 = r * Math.sin (i*angle);
      
      	    // The second corner:
      	    double x2 = r * Math.cos ((i+1)*angle);
      	    double y2 = r * Math.sin ((i+1)*angle);
      
      	    // Distance between the two:
      	    double dist = Math.sqrt ((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2));
      
      	    // Accumulate:
      	    perimeter = perimeter + dist;
      
      	    // Draw the i-th triangle:
      	    DrawTool.drawLine (0,0, x1, y1);
      	    DrawTool.drawLine (0,0, x2, y2);
      	    DrawTool.drawLine (x1,y1, x2, y2);
      	}
      
      	// The estimate of π is the perimeter divided by the diameter.
      	double piEstimate = perimeter / (2*r);
      	System.out.println ("pi=" + piEstimate);
          
      Note: Ignore the trigonometry for the moment and just pay attention to:
      • We have a loop that runs N times.
      • In each iteration we compute the coordinates of the i-th triangle.
      • One of the edges of the i-th triangle (the one with endpoints on the circle) is part of the perimeter.
      • We add its length to the perimeter (the distance between the end points).
      • Later, we divide the perimeter by the diameter, and we're done.
       

      8.20 Exercise: Uncomment the main loop in ArchimedesSteps.java to see the rest.

    • As an exercise (not required) you can work through the trigonometry to explain the calculation of the coordinates.
     

    Lastly, we would be remiss if we did not point out a faster way of achieving the same result:

    • Since each polygon edge is of the same length, do we really need to calculate the length of each and every one of them?

    • No. We could compute the length of one of them and multiply by N.

    • Here's the code:
      	// Radius:
      	double r = 8;
      
      	// Number of triangles to inscribe:
      	int N = 100;
      
      	// Interior angle of each:
      	double angle = 2*Math.PI / N;
      
      	// The corner of the triangle touching the x-axis:
      	double x1 = r;
      	double y1 = 0;
      
      	// The second corner:
      	double x2 = r * Math.cos (angle);
      	double y2 = r * Math.sin (angle);
      
      	// Distance between the two:
      	double dist = Math.sqrt ((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2));
      
      	// Multiply by N:
      	double perimeter = N * dist;
      
      	// The estimate of is the perimeter divided by the diameter:
      	double piEstimate = perimeter / (2*r);
      	System.out.println ("pi=" + piEstimate);
          

    • This is probably how Archimedes did it.

    • Why, then, did we use a for-loop?
             ⇒ We needed it to draw the different triangles.
      • The coordinates of the different triangles are different.
      • Each needed calculation, which is why the loop was necessary.
       

      8.21 Exercise: Download ArchimedesFast.java, compile and run. Increase N for higher accuracy.

    • In fact, Archimedes did one more thing:
      • He used a second sequence with polygons that circumscribe the circle, like this one:

      • Both sequences converge to the circumference.
      • He used the average of the two for some fairly accurate estimates.
    Lastly, we'll point out that this last section was mostly an exercise in reading and seeing how concepts learned earlier can be applied. And to pay our respects to Archimedes, of course.
     

    8.22 Audio:
     

    On to Assignment 2


    © 2017, Rahul Simha