next_inactive up previous
Up: MX3015 Home Page

MX3015: Mathematical Computation

Ian Craw

Sheet 7: Using Formulae

At the end of this practical, you should be happier programming ``formulae''; for summing series or for finding the roots of a quadratic.

The classes this week are in the package uk.ac.abdn.maths.mx3015.formulae. You will find a new directory and some prototype classes in the current version of mx3015.jar. Start work by extracting it as usual into the directory mx3015. Here are the commands, assuming you've just logged in:

bash% cd mx3015
bash% jar xvf f:/data/mx3015/mx3015.jar
bash% cd src/uk/ac/abdn/maths/mx3015/formulae


Question 7.1

You are given a copy of an incomplete QuadFormula class, which runs but does not produce sensible answers. Write the void solve() method which is called during construction, to store the roots of the quadratic. These should be found using the usual quadratic formula. Check that the quadratics constructed in the main method behave as you would expect. Here is the shell of the class; paste it into your editor to get started.
package uk.ac.abdn.maths.mx3015.formulae;

import java.io.PrintStream;
import java.text.NumberFormat;

/**
 * This class instantiates a quadratic written as ax^2 + bx + c.
 * This version simply solves using the quadratixc formula, without
 * worrying about the loss of precision which may occur when
 * subtracting two numbers of a similar size.
 *
 * @version $Revision: 3.1 $
 * @author  Your name here!
 */
public class QuadFormula {

    /** The coefficient of x^2. */
    private double a;

    /** The coefficient of x. */
    private double b;

    /** The constant term. */
    private double c;

    /** Declare whether we have real or complex roots */
    public boolean hasRealRoots;

    /** 
     * The root with the larger modulus - only useful if
     * <code>hasRealroots</code> is true.
     **/
    public double root1;

    /** 
     * The root with the smaller modulus - only useful if
     * <code>hasRealroots</code> is true.
     **/
    public double root2;

    /** 
     * The real part of a pair of complex roots - only useful if
     * <code>hasRealroots</code> is false, so the Quadratic has
     * complex roots
    **/
    public double realPart;

    /** 
     * The imaginary part of a pair of complex roots - only useful if
     * <code>hasRealroots</code> is false, so the Quadratic has
     * complex roots
    **/
    public double imaginaryPart;

    /** 
     * The constructor is responsible for checking we <em>have</em> a
     * quadratic.  It initialises the constructor and then calls
     * <code>solve</code> which solves the quadratic using the formula
     * and sets the roots appropriately.
     **/
    public QuadFormula (double a, double b, double c) {
	if (a == 0) {
	    throw new IllFormedQuadraticException();
	}
	this.a = a;
	this.b = b;
	this.c = c;
	solve();
    }

    /**
     * Obtain either two real rools or the real and imaginary parts of
     * the two complex roots, necesarily conjugate since the
     * coefficients are real.  Sets the boolean
     * <code>hasRealRoots</code> and <em>exactly</em> two of the four
     * instance variables which store the roots.
     **/
    public void solve() {
	double discriminant = b*b - 4*a*c;
	//-> You do it.
	//<- Finish this way; then test
    }
    /** A convenience method to display Quadratics. */
    public String toString() {
	return (a+" x^2 + " + b + " x + " + c);
    }
    /** 
     * Purely for testing - print the roots.  Note that "System.out"
     * is a perfectly sensible PrintStream. 
     **/
    public void printRoots(PrintStream out) {
	// The next three lines use more advanced language features.
	// to control how much space each entry takes up.
	NumberFormat nf = NumberFormat.getInstance();
	nf.setMaximumFractionDigits(2);
	nf.setMinimumFractionDigits(2);
        StringBuffer sb = new StringBuffer();
        sb.append("The quadratic " + this) ;
	if (hasRealRoots) {
            sb.append(" has real roots " + nf.format(root1) 
                        + " and " + nf.format(root2) + ".");
	} else {
	    sb.append(" has complex roots " + nf.format(realPart) 
                        + " +/- i " + nf.format(imaginaryPart) + ".");
	}
        out.println(sb);
    }

    /** Create some quadratics to test the class. */
    public static void main(String argv[]) {
	QuadFormula p = new QuadFormula(1.0,5.0,6.0);
	p.printRoots(System.out);
	p = new QuadFormula(2.0,-4.0,4.0);
	p.printRoots(System.out);
	p = new QuadFormula(1,-2.0,1.0);
	p.printRoots(System.out);
	p = new QuadFormula(1.0,10000.0,1.0);
	p.printRoots(System.out);
	p = new QuadFormula(1.0,-10000.0,1.0);
	p.printRoots(System.out);
	try{ // This one should fail.
	    p = new QuadFormula(0.0,-10000.0,1.0);	
	    p.printRoots(System.out);
	} catch (Exception e) {
	    // Just continue
	}
    }
    /** Purpose built exception class just to report the error. **/ 
    class IllFormedQuadraticException extends RuntimeException {
    // Just need a constructor.
	IllFormedQuadraticException() {
	    System.out.println("The quadratic term must be non-zero.");
	}
    }
}
You will also find a copy in the file QuadFormula.java.in. It is in the updated distribution; remember to rename the file before starting work.

Question 7.2

(For your portfolio.) Now start with a new Quadratic class. Copy your implementation of the solve() method from the previous question, and modify it to use the ``product of roots'' method, discussed in (last) Monday's lecture, to derive the root with the smaller modulus.

Then extend the main method to solve a collection of quadratics. Their coefficients are specified in a file quadratics.dat; take the first double on each line to be the coefficient of $ x^2$ and so on. You are to write the output to roots.dat. You will need to continually read a line of input, create the corresponding quadratic and write the roots to the output. Recall the ideas you practiced in the uk.ac.abdn.maths.mx3015.files package. Here is the shell of the class; paste it into your editor to get started.

package uk.ac.abdn.maths.mx3015.formulae;

import java.io.*;
import java.text.NumberFormat;
import java.util.StringTokenizer;

/**
 * This class instantiates a quadratic written as ax^2 + bx + c.
 *
 * @version $Revision: 3.1 $
 * @author  Your name here!
 */
public class Quadratic {

    /** The coefficient of x^2. */
    private double a;

    /** The coefficient of x. */
    private double b;

    /** The constant term. */
    private double c;

    /** Declare whether we have real or complex roots */
    public boolean hasRealRoots;

    /** 
     * The root with the larger modulus - only useful if
     * <code>hasRealroots</code> is true.
     **/
    public double root1;

    /** 
     * The root with the smaller modulus - only useful if
     * <code>hasRealroots</code> is true.
     **/
    public double root2;

    /** 
     * The real part of a pair of complex roots - only useful if
     * <code>hasRealroots</code> is false, so the Quadratic has
     * complex roots
    **/
    public double realPart;

    /** 
     * The imaginary part of a pair of complex roots - only useful if
     * <code>hasRealroots</code> is false, so the Quadratic has
     * complex roots
    **/
    public double imaginaryPart;

    /** 
     * The constructor is responsible for checking we <em>have</em> a
     * quadratic.  It initialises the constructor and then calls
     * <code>solve</code> which solves the quadratic using the formula
     * and sets the roots appropriately.
     **/
    public Quadratic (double a, double b, double c) {
	if (a == 0) {
	    throw new IllFormedQuadraticException();
	}
	this.a = a;
	this.b = b;
	this.c = c;
	solve();
    }

    /**
     * Obtain either two real rools or the real and imaginary parts of
     * the two complex roots, necesarily conjugate since the
     * coefficients are real.  Sets  the boolean
     * <code>hasRealRoots</code> and </em>exactly</em> two of the four
     * instance variables which store the roots.
     **/
    public void solve() {
	double discriminant = b*b - 4*a*c;
	// Code needs writing
	//-> You do it.
	//<- Finish this way; then test
    }
    /** A convenience method to display Quadratics. */
    public String toString() {
	return (a + " x^2 + " + b + " x + " + c);
    }
    /** 
     * Purely for testing - print the roots.  Note that "System.out"
     * is a perfectly sensible PrintStream. 
     **/
    public void printRoots(PrintStream out) {
	// The next three lines use more advanced language features.
	// to control how much space each entry takes up.
	NumberFormat nf = NumberFormat.getInstance();
	nf.setMaximumFractionDigits(2);
	nf.setMinimumFractionDigits(2);
        StringBuffer sb = new StringBuffer();
        sb.append("The quadratic " + this) ;
	if (hasRealRoots) {
            sb.append(" has real roots " + nf.format(root1) 
                        + " and " + nf.format(root2) + ".");
	} else {
	    sb.append(" has complex roots " + nf.format(realPart) 
                        + " +/- i " + nf.format(imaginaryPart) + ".");
	}
        out.println(sb);
    }

    /** Create some quadratics to test the class. */
    public static void main(String argv[]) {
	Quadratic p = new Quadratic(1.0,5.0,6.0);
	p.printRoots(System.out);
	p = new Quadratic(2.0,-4.0,4.0);
	p.printRoots(System.out);
	p = new Quadratic(1,-2.0,1.0);
	p.printRoots(System.out);
	p = new Quadratic(1.0,10000.0,1.0);
	p.printRoots(System.out);
	p = new Quadratic(1.0,-10000.0,1.0);
	p.printRoots(System.out);
	try{ // This one should fail.
	    p = new Quadratic(0.0,-10000.0,1.0);	
	    p.printRoots(System.out);
	} catch (Exception e) {
	    // Just continue
	}
	//-> Finally set up reading and writing to file.
	//<- and finish this way
    }
    /** Purpose built exception class just to report the error. **/ 
    class IllFormedQuadraticException extends RuntimeException {
	// Just need a constructor.
	IllFormedQuadraticException() {
	    System.out.println("The quadratic term must be non-zero.");	}
    }
}
You will also find a copy in the file Quadratic.java.in. It is in the updated distribution; remember to rename the file before starting work.


Question 7.3

Use the formula

$\displaystyle \exp(x) = 1 + x + \frac{x^2}{2!} \dots + \frac{x^{n}}{n!} + \dots
$

to write your own Exp function. Follow the outline discussed in the lecture. Compare the answers your method gives with those obtained by the built-in Math.exp(double x) method. Here is the shell of the class; paste it into your editor to get started.
package uk.ac.abdn.maths.mx3015.formulae;
import  uk.ac.abdn.maths.mx3015.util.Evaluable;

/**
 * Calculating exp(x) by summing the series.
 * @author Your name here! 
 **/
public class Exp implements Evaluable {

    /** Minimal size of term to include in the sum. **/
    private double epsilon = 1E-8;

    /** No argument constructor picks up the default value of epsilon. **/
    Exp() {}

    /** Construct with a chosen value of epsilon. **/
    Exp(double eps) {
	epsilon = eps;
    }
    
    /**
     * Evaluate exp(x) using the power series.  This is where the
     * <code> Evaluable</code> interface is implemented.
     * @param x the <code>double</code> value at which the 
     *                          series should be evaluated.
     * @return a <code>double</code> which is the sum of the series.
     */
    public double at(double x) {
	double sum = 1;
	//-> Now you do it.
	//<- Finishing this way.
	return sum;
    }

    /** The main method  is simply here to test the class. **/	
    public static void main(String [] argv) {
	double value = 1;
	Exp exp = new Exp();
	System.out.println("We get " + exp.at(value) + 
			   "; the system gets " + Math.exp(value));
	exp = new Exp(1.0E-14);
	System.out.println("We get " + exp.at(value) + 
			   "; the system gets " + Math.exp(value));
    }
}
You will also find a copy in the file Exp.java.in. It is in the updated distribution; remember to rename the file before starting work.


Question 7.4

This one should be very similar, but you will find the convergence is very much slower if $ \vert x\vert$ is close to $ 1$. Use the formula

$\displaystyle \ln(1 + x) = x - \frac{x^2}{2} + \frac{x^3}{3} + \dots
(-1)^{n+1}\frac{x^n}{n} + \dots\qquad(\vert x\vert < 1).
$

to write your own ln(1 + x) function, varying the ideas just used. Compare the answers your method gives with those obtained by the built-in Math.log(double x) method. Here is the shell of the class; paste it into your editor to get started.
package uk.ac.abdn.maths.mx3015.formulae;
import  uk.ac.abdn.maths.mx3015.util.Evaluable;

/**
 * Calculating log(1+x) by summing the series.  We use:
 * log(1 + x) = x - x^2/s + x^3/3 ..., which is valid for |x| < 1
 * @author Your name here! 
 **/
public class Log implements Evaluable {

    /** Minimal size of term to include in the sum. **/
    private double epsilon = 1E-8;

    /** No argument constructor picks up the default value of epsilon. **/
    Log() {}

    /** Construct with a chosen value of epsilon. **/
    Log(double eps) {
	epsilon = eps;
    }

    /**
     * Evaluate log(1+x) using the power series.  This is where the
     * <code> Evaluable</code> interface is implemented.
     * @param x the <code>double</code> value at which the 
     *                          series should be evaluated.
     * @return a <code>double</code> which is the sum of the series.
     */
    public double at(double x) {
	double sum = x;
	//-> Now you do it.
	//<- Finishing this way.
	return sum;
    }

    /** The main method  is simply here to test the class. **/
    public static void main(String [] argv) {
	double value = -0.95;
	Log log = new Log();
	System.out.println("We get " + log.at(value) + 
			   "; the system gets " + Math.log(1+value));
	log = new Log(1.0E-14);
	System.out.println("We get " + log.at(value) + 
			   "; the system gets " + Math.log(1+ value));
    }
}
You will also find a copy in the file Log.java.in. It is in the updated distribution; remember to rename the file before starting work.

Question 7.5

(For your portfolio.) Use the formula

$\displaystyle \sin(x) = x - \frac{x^3}{3!} + \frac{x^5}{5!} - \dots +
(-1)^n\frac{x^{2n+1}}{(2n+1)!} + \dots
$

to write your own Sine function, varying the ideas just used. If you can, take advantage of the periodicity if $ \sin(x)$; that $ \sin(x + 2k\pi) = \sin(x)$ for $ k \in \mathbb{Z}$, to apply the series to an argument $ x$ with $ -\pi < x \leqslant \pi$, thus speeding up the convergence. You may wish to use the Math.floor(double x) function. Compare the answers your method gives with those obtained by the built-in Math.sin(double x) method. Here is the shell of the class; paste it into your editor to get started.
package uk.ac.abdn.maths.mx3015.formulae;
import  uk.ac.abdn.maths.mx3015.util.Evaluable;

/**
 * Calculating sin(x) by summing the series.
 * @author Your name here! 
 **/
public class Sine implements Evaluable {

    /** Calculate, once and for all, a constant we use regularly. **/
    static final double twoPi = 2*Math.PI;

    /** Minimal size of term to include in the sum. **/
    private double epsilon = 1E-8;

    /** No argument constructor picks up the default value of epsilon. **/
    Sine() {}

    /** Construct with a chosen value of epsilon. **/
    Sine(double eps) {
	epsilon = eps;
    }
    /**
     * Returns the number between -pi and pi which differs from
     * <code>x</code> by a multiple of <code>2*Math.PI</code>
     * @param x the <code>double</code> which is to be reduced mod 2*PI.
     * @return the <code>double</code> reduced value
     */
    double reduce(double x) {
	//-> There are many ways to do this.
	//<- Finish this way.  The rest will work anyway.
	return x;
    }
    /**
     * Evaluate sin(x) using the power series.
     * @param x the <code>double</code> value at which the 
     *                          series should be evaluated.
     * @return a <code>double</code> which is the sum of the series.
     */
    double sumSeries(double x) {
	double sum = x;
	//-> Your aim is to return the sum of the sine series.
	//<- Finishing this way.
	return sum;
    }

    /**
     * The <code>at</code> method does the actual evaluation, first
     * reducing the argument to lie between -PI and PI before summing
     * the series.  This is where the <code>Evaluable</code>
     * interface is implemented.
     *
     * @param x the <code>double</code> value at which the 
     *                          series should be evaluated.
     * @return a <code>double</code> which is the sum of the series.
     */
    public double at(double x) {
	return (sumSeries(reduce(x)));
    }
	
    /** The main method  is simply here to test the class. **/	
    public static void main(String [] argv) {
	double angle = Math.PI/4;

	Sine sine = new Sine();
	System.out.println("We get " + sine.at(angle) + 
			   "; the system gets " + Math.sin(angle));
	sine = new Sine(1.0E-14);
	System.out.println("We get " + sine.at(angle) + 
			   "; the system gets " + Math.sin(angle));
    }
}
You will also find a copy in the file Sine.java.in. It is in the updated distribution; remember to rename the file before starting work.


Question 7.6

Write a class each of whose objects is a ``general'' polynomial; in other words a polynomial of degree $ n$. Arrange for it to implement the Differentiable interface. Write suitable methods including ones to add and multiply two polynomials. Although you will probably find this class is quite like the MathVec class, note the difference here; that it is perfectly sensible to try to add two polynomials of different degrees. You will probably find it much easier to write other methods if you first get accessor and mutator methods right.

Here is the shell of the class; paste it into your editor to get started.

package uk.ac.abdn.maths.mx3015.formulae;
import  uk.ac.abdn.maths.mx3015.util.*;
import java.io.*;
/**
 * A simple implementation of Polynomials.
 *
 * @author Your name here! 
 **/
public class Polynomial implements Differentiable {
    /** The degree of the polynomial. */
    int degree;

    /** The actual storage */
    private double[] coefficient;

    /** It is convenient to allow initialisation from an array */
    public Polynomial(double[] newval) {
	degree = newval.length -1;	
	coefficient = new double[degree + 1];
	for( int i = 0; i <= degree; i++) {
	    coefficient[i] = newval[degree-i];
	}
    }
    //-> There are many methods to add.
    //<- Remember you must define this
    /**
     * To implement the Evaluable interface, we must define the "at"
     * method which evaluates the polynomial at a given point.  Nested
     * multiplication significantly reduces the number of operations
     * used by writing the polynomial as (...((a_n x + a_{n-1}) x +
     * a_{n-2})... ) x + a_0 
     */
    public double at(double x) {
	double result = 0; // initialiser not used
	//-> So start work
	//<- Finish this way.
	return result;
    }
    //-> Over to you again.
    //<- Remember you must define this
    /**
     * To implement the Differentiable interface, we must define the
     * <code> dash </code> method which evaluates the derivative of
     * the polynomial at a given point.  We've essentially done the
     * work already.
     **/
    public double dash(double x){
	double result = 0; // initialiser not used
	//-> So start work
	//<- Finishing correctly
	return result;
    }
    //-> Again back to you.
//    //<-// Uncomment here when you have written the methods
//    public String toString() {
//	StringBuffer sb = new StringBuffer();
//	for (int i = degree; i >0; i--) {
//	    sb.append(getCoef(i) + "x^" + i + " + ");
//	}
//	sb.append(getCoef(0)); 
//	return sb.toString();
//    }
//    //->// This gives a sensible display.
    //<- Start testing
    /** Create some polynomials to exercise the class. */
    public static void main(String argv[]) {
	double a[] = {6,5,1};
	Polynomial p = new Polynomial(a);
	System.out.println("Creating the polynomial p gives:      " + p + ".");
	double b[] = {1,2,3,4,5};
	Polynomial q = new Polynomial(b);
	System.out.print("Creating the polynomial q of degree ");
	System.out.println( q.degree+ " gives:      " + q + ".");
	//-> Now add your testing
	//<- And finish this way.
    }
}
You will also find a copy in the file Polynomial.java.in. It is in the updated distribution; remember to rename the file before starting work.

About this document ...

MX3015: Mathematical Computation

This document was generated using the LaTeX2HTML translator Version 2002-1 (1.67)

Copyright © 1993, 1994, 1995, 1996, Nikos Drakos, Computer Based Learning Unit, University of Leeds.
Copyright © 1997, 1998, 1999, Ross Moore, Mathematics Department, Macquarie University, Sydney.

The command line arguments were:
latex2html -init_file formulae.l2hinit -debug -verbosity 1 -init_file /home/igc/tools/include/.latex2html-init -t 'MX3015: Mathematical Computation' -up_url ../index/index.html -up_title 'MX3015 Home Page' -split 0 formulae

The translation was initiated by Ian Craw on 2003-12-04


next_inactive up previous
Up: MX3015 Home Page
Ian Craw 2003-12-04