Spring Semester 2003


Lecture Notes Fifteen: Designing Fractions.
You mentioned De Morgan's name yesterday. Augustus De Morgan (1806-1871), indeed.
http://www-groups.dcs.st-andrews.ac.uk/~history/Mathematicians/De_Morgan.html

De Morgan was the one that, in 1838, defined and introduced the term mathematical induction, thus putting a process that had been used without clarity on a rigorous basis. I don't know if he ever played Nim, but here's how he was described by some of his colleagues: "A dry dogmatic pedant I fear is Mr De Morgan, notwithstanding his unquestioned ability."

In 1866 he was a co-founder of the London Mathematical Society and became its first president. De Morgan was never a Fellow of the Royal Society as he refused to let his name be put forward. He also refused an honorary degree from the University of Edinburgh.

He recognised the purely symbolic nature of algebra and he was aware of the existence of algebras other than ordinary algebra. He introduced De Morgan's laws and his greatest contribution is as a reformer of mathematical logic.

Very interesting. What other mathematicians were involved in the lecture notes of yesterday? Charles Lutwidge Dodgson (1832-1898).
http://www-groups.dcs.st-andrews.ac.uk/~history/Mathematicians/Dodgson.html

Here's a picture of him. Yes, he's the one in the middle.

Charles Dodgson is known especially for Alice's adventures in wonderland (1865) and Through the looking glass (1872), children's books that are also distinguished as satire and as examples of verbal wit. He invented his pen name of Lewis Carroll by anglicizing the translation of his first two names into the Latin 'Carolus Lodovicus'.

As a mathematician, Dodgson was conservative. He was the author of a fair number of mathematics books, for instance A syllabus of plane algebraical geometry (1860).

None of his math books have proved of enduring importance except for Euclid and his modern rivals (1879) which is of historical interest. As a logician, he was more interested in logic as a game than as an instrument for testing reason.

"I know what you're thinking about," said Tweedledum: "but it isn't so, nohow." "Contrariwise," continued Tweedledee, "if it was so, it might be; and if it were so, it would be: but as it isn't, it ain't. That's logic."

He contributed in Jabberwocky, the word chortle (a word that combines snort and chuckle) to the English language.
frilled.cs.indiana.edu%webster chortle
chor-tle vb  chor-tled; chor-tling 
[blend of chuckle and snort]
vi
(1872)
1: to sing or chant exultantly <he chortled in his joy --Lewis
     Carroll>
2: to laugh or chuckle esp. in satisfaction or exultation
~ vt :to say or sing with a chortling intonation
-- chortle n 
-- chor-tler n 

frilled.cs.indiana.edu%
Yet momeraths and brillig didn't quite make it.

Today we're going to implement Fractions. And in the process mention Euclid (325-265).
http://www-groups.dcs.st-andrews.ac.uk/~history/Mathematicians/Euclid.html

Have you noticed the numbers? Yes, that was a long time ago!

Euclid's most famous work is his treatise on mathematics The Elements. The book was a compilation of knowledge that became the centre of mathematical teaching for 2000 years.

The Elements is divided into 13 books. Books one to six deal with plane geometry.

Books seven to nine deal with number theory. In particular book seven is a self-contained introduction to number theory and contains the Euclidean algorithm for finding the greatest common divisor of two numbers.

Which we will use today. Very good.

A fraction is of course the ratio of two integers:
  • a numerator and
  • a denominator
We will define a class Fraction, which will supply the necessary operations on fractions.

There are many ways in which we could do this. Here's a summary, to be augmented with a more detailed explanation in class.

Let's look first at the new part. Of which there are two parts, as well.
class Euclid {
    static int gcd(int a, int b) {
        a = Math.abs(a);
        b = Math.abs(b);
        if (a == 0) return b; // 0 is error value
        if (b == 0) return a;
        int temp;
        while (b > 0) {
            temp = a % b;
            a = b;
            b = temp;
        }
        return a;
    }
}
We need to get the hang of it, first.

Then, when we become comfortable using it, we need to become sure it always works right. Proof is the bottom line for everyone.

That's from Paul Simon, isn't it? Yes, but it applies here.

Both goals may take a long time. But when you're done you can write Fraction.

Like this. That's a lot.
class Fraction {

    private int numerator;
    private int denominator;

    public Fraction(int num, int den) {
        int divisor;
        if (den == 0) {
            System.out.println(" Fraction with denominator zero!");
            System.exit(1);
        }
        if (num == 0) { numerator = 0; denominator = 1; }
        else {
            if (den < 0) {
                num *= -1;
                den *= -1;
            }
            if ((divisor = Euclid.gcd(num, den)) != 1) {
                num /= divisor;
                den /= divisor;
            }
            numerator = num;
            denominator = den;
        }
    }

    public String toString() {
        String fraction;
        if (denominator == 1) { fraction = numerator + ""; }
        else { fraction = numerator + "/" + denominator; }
        if (denominator * numerator < 0) {
            return "(" + fraction + ")";
        } else {
            return fraction;
        }

    }

    public boolean isZero() {
        return (denominator == 1 && numerator == 0);
    }

    public boolean isInt() {
        return (denominator == 1);
    }

    public boolean equals(Fraction other) {
        return (numerator == other.numerator && denominator == other.denominator);
    }

    public boolean greaterThan(Fraction other) {
        return (numerator * other.denominator >
                denominator * other.numerator);
    }

    public Fraction minus(Fraction other) {
        return new Fraction(
                     numerator * other.denominator - other.numerator * denominator,
                     denominator * other.denominator
                   );
    }

    public Fraction plus(Fraction other) {
        return new Fraction(
                     numerator * other.denominator + other.numerator * denominator,
                     denominator * other.denominator
                   );
    }

    public Fraction times(Fraction other) {
        return new Fraction(numerator * other.numerator, denominator * other.denominator);
    }

    public Fraction divideBy(Fraction other) {
        return new Fraction(numerator * other.denominator, denominator * other.numerator);
    }

    public static void main(String[] args) {
        Fraction f = new Fraction(6, 9);
        Fraction g = new Fraction(-4, 6);
        System.out.println("Test of operations: ");
        System.out.println("  Add: " + f + " + " + g + " = " + f.plus(g));
        System.out.println("  Sub: " + f + " - " + g + " = " + f.minus(g));
        System.out.println("  Mul: " + f + " * " + g + " = " + f.times(g));
        System.out.println("  Div: " + f + " / " + g + " = " + f.divideBy(g));
        System.out.println("Test of predicates: ");
        System.out.print("  1. Does " + f + " equal " + g + "? ");
        System.out.println(" The answer is: " + f.equals(g));
        Fraction h = new Fraction(8, -2);
        System.out.print("  2. Is " + h + " an integer? ");
        System.out.println("The answer is: " + h.isInt());
        Fraction i, j;
        i = (f.minus(g)).times(f.plus(g));
        j = f.times(f).minus(g.times(g));
        System.out.print("  3. Does " + i + " equal " + j + "? ");
        System.out.println("The answer is: " + i.equals(j));
        System.out.print("  4. Is 5/8 greater than 2/3? The answer is: ");
        System.out.println((new Fraction(5, 8)).greaterThan(new Fraction (2, 3)));

    }
}

There are two parts to it. First, the blueprint.

Then, the main. Both important.

When you're done you can improve it.
boolean equals(Fraction other) {
    return (this.minus(other)).isZero(); 
} 
That's a different equals.

Here's a different greaterThan.
boolean greaterThan(Fraction other) {
    return (this.minus(other)).isPositive(); 
} 
That wouldn't work just yet.

I know, you need another predicate. Can I write it?

Sure, what's its signature? boolean isPositive() is it's signature.

It's a simple one. I agree.
boolean isPositive() {
    return numerator * denominator > 0; 
} 

This was a long example. Long, but useful.

And interesting. If you say so...

Last updated: Mar 3, 2003 by Adrian German for A201