# trying to understand this rational numbers class

• 03-28-2010, 05:44 AM
sonny
trying to understand this rational numbers class
So, i am now upto learning about classes & objects,
I have a rational number class to work with fractions i didnt write this class, it is part of my study text and i'm trying to understand how it works. so i thought i would write a run method to utilise this class to do calculations with fractions. (or subtract or multiply but for the purpose of this post just adding, i can figure in while loops and sentinels etc later)

i am not sure whether its a simply syntax issue that i haven't got my head around, or whether its the issue of using classes that i haven't got my head round,,
its probably a bit of both.
my run method gets all confused towards the end and doesn't make any sense theres all kind of rubbish at the end of the last method because i just left the rubbish in there so you could see where my thinking was at.
here is the class code for the Rational class

Code:

```public class Rational { /** Creates a new Rational initialised to zero. */         public Rational(){                 this (0);         } /** Creates a new Rational from the integer argument. * @param n The initial value */         public Rational(int n) {                 this(n,1); } /** Creates a new Rational with the value x / y. * @param x The numerator of the rational number * @param y The denominator of the rational number */         public Rational(int x, int y) {                 if(y==0)throw new ErrorException (" Cannot Divide by Zero");                 int g = gcd(Math.abs(x),Math.abs(y));                 num = x / g;                 den = Math.abs(y) / g;                 if (y < 0) num = -num;         }         /** Adds the rational number r to this one and returns the sum. * @param r The rational number to be added * @return The sum of the current number and r */                public Rational add(Rational r) {                 return new Rational(this.num * r.den + r.num * this.den, this.den * r.den);                 }         /** Subtracts the rational number r from this one. * @param r The rational number to be subtracted * @return The result of subtracting r from the current number */         public Rational subtract(Rational r) {                 return new Rational(this.num * r.den - r.num * this.den, this.den * r.den);         }         /** Multiplies this number by the rational number r. * @param r The rational number used as a multiplier * @return The result of multiplying the current number by r */         public Rational multiply(Rational r) {                 return new Rational(this.num * r.num, this.den * r.den);         }         /** Divides this number by the rational number r. * @param r The rational number used as a divisor * @return The result of dividing the current number by r */         public Rational divide(Rational r) {                 return new Rational(this.num * r.den, this.den * r.num);         }         /** Calculates the greatest common divisor using Euclid's algorithm. * @param x First integer * @param y Second integer * @return The greatest common divisor of x and y */         private int gcd(int x, int y) {                 int r = x % y;                 while (r != 0) {                         x = y;                         y = r;                         r = x % y;                 }                 return y;         } /** * Creates a string representation of this rational number. * @return The string representation of this rational number */         public String toString() {                 if (den == 1) {                         return "" + num;                 } else {                         return num + "/" + den;                 }         }                        /* Private instance variables */         private int num; /* The numerator of this Rational */         private int den; /* The denominator of this Rational */                 }```
and here is my program/run method which makes no real sense, but to reiterate my question how to i define one object,(which i have done) and add to another object.
Code:

```import acm.program.ConsoleProgram; public class UseRational extends ConsoleProgram{         public void run(){                 intro();                 enterFraction();         }         private void intro() {}         private void enterFraction() {                 int num=readInt("  Numerator: ");                 int den=readInt("Denominator: ");                 Rational one = new Rational(num,den);                 println(one);                 enterOperation (one);         }         private void enterOperation(Rational one) {                 String op = readLine("+, -, x, /, ");                 enterNextFraction(one,op);         }         private void enterNextFraction(Rational one, String op) {                 int num=readInt("  Numerator: ");                 int den=readInt("Denominator: ");                 Rational result = one add Rational(num,den);                 println(result);                                 if(op.equals("+")){                         Rational result = one add.Rational two;                         println(one+" + "+two+" = "+one add Rational two);                 }                         if(op.equals("-"))                         if(op.equals("x"))                         } }```

Sonny.
• 03-28-2010, 06:03 AM
m00nchile
As I see it, your main problem is not knowing how to call the methods from the Rational class. Since the methods are not static (i.e. they're object or instance methods) you call on them like this:
Code:

```MyClass c = new MyClass(); //first create an instance c.doSomething(); //execute a method```
In your case you would do something like this:
Code:

```Rational first = new Rational(3,5); Rational second = new Rational(1,2); Rational result = first.add(second);```
You invoke the add method of the first rational number, if we take a look at it:
Code:

```public Rational add(Rational r) {                 return new Rational(this.num * r.den + r.num * this.den, this.den * r.den);                 }```
add recieves the argument r of the type Rational, when you called the method with first.add(second), second is r from the method definition, so in this case, this.num = 3, this.den = 5 (from first), r.num = 1, r.den = 2 (from second). I'd suggest doing a few simple exercises with classes, to get to grips with differences between objects and classes, static and instance fields and methods.
• 03-28-2010, 06:06 AM
Fubarable
You may be biting off more than you can chew here trying both to use the Rational class and get user input. Why not try to use Rational in a simpler set up. Don't get user input but rather hard code a few Rational variables and try to get it to work on these. I'd start with a single main method in your UseRational class, and then create two Rational variables. Try then to use the add method to add these variables, place the sum into a third Rational variable and display it. Do that much, get it to work, and THEN work on extending things. Small steps at a time.

Best of luck!
• 03-28-2010, 07:00 AM
sonny
thanks for the help guys
thanks very much guys,

i half suspected that maybe I had bitten off more than i could chew, once i got started, cos I jumped a good way forward in the text, but thought i would figure it out.,, and maybee m00nchiles post will make a bit more sense in the morning and ill get there.

I kinda see whats going on, its kinda like scaling up the ideas of methods, or like calling up a new GRect, but this time i want to do more than just add it to my canvass, i want to combine it with another GRect and add that result to my canvass,, it hasn't totally gelled yet in my head and yes maybe I need to break it down into smaller chunks. using hard code examples.

i think im gonna do some simpler exercises from the text first and keep coming back to this idea once the notion of classes sinks in a bit better.

kind regards
• 03-28-2010, 09:15 AM
gcalvin
Sonny, this is really not beyond your grasp, and I don't believe Fubarable was trying to say that it was. He was just saying that trying to learn this class and trying to learn the complexities of console input at the same time is maybe not a great idea.

I think a Rational class is a great example to study. It's complex enough to be interesting, but still simple enough to understand completely. It's useful (well, at least potentially useful) and it illustrates object oriented programming concepts quite nicely.

First of all, we should wrap our heads about what rational numbers are in "real life". They are simply numbers that can be expressed as a ratio of two integers. So 1/3, 7/8, 4/9, 22/7 are all rational numbers. Three and a half is a rational number, but if we write it as 3-1/2, as it sometimes appears in text, it's potentially confusing, because "-" usually means subtraction. So we prefer to write it as 7/2. Also, 12/36 is a rational number, but we prefer to express it in its simpler form, 1/3.

OK, so now we know enough to get started -- we know that the essence of a rational number is two integers: a numerator and a denominator.
Code:

```public class Rational {     private int numerator;     private int denominator;```
(By the way, the author of your text likes to put his instance variables at the bottom of the class for some reason, and Mehran in the video course does the same thing. I think most Java programmers put them at the top.)

OK, now we can think about a constructor. The constructor that makes the most sense is one that takes the numerator and denominator as parameters.
Code:

```    public Rational(int numerator, int denominator) {         this.numerator = numerator;         this.denominator = denominator;     }```
(The author uses different names -- num and den for the ivars, x and y for the parameters. I like my names better.)

That much is OK as far as it goes, but there are a couple of problems. First, denominator better not be zero. The text handles that with an ErrorException, which is part of the ACM libraries the CS106A course uses (and almost nobody else in the modern Java world seems to use), but I'll use a regular Exception for now. (We really should be subclassing our own Exception class, but we'll do that another time.) The reason why I want to do it that way is because the ACM ErrorException class sort of "swallows" the Exception instead of doing things The Java Way. Anyway, our constructor now looks like this:
Code:

```    public Rational(int numerator, int denominator) throws Exception {         if (0 == denominator) throw new Exception("Cannot divide by zero.");         this.numerator = numerator;         this.denominator = denominator;     }```
Note the "throws" clause on the top line -- that's the standard Java way of warning that a method can generate Exceptions. (Also, putting the constant on the left side of the == operator is an old trick to protect against accidentally using a single = .)

OK, we're just about done, but if somebody does
Code:

```[COLOR="Blue"]                Rational r = new Rational(12, 36); [/COLOR]```
we don't want to store it as 12/36, we want to store it as 1/3 -- simplifying or reducing the fraction. In order to do that (if we remember our fourth grade math), we have to find the Greatest Common Divisor (GCD) shared by the numerator and denominator. We'll write a helper method to do that -- don't worry too much about understanding that method right now. Once we find the GCD, we divide both the numerator and denominator by it. Also, we should make sure the denominator is positive (changing the sign of the numerator if necessary).
Code:

```    public Rational(int numerator, int denominator) throws Exception {         if (0 == denominator) throw new Exception("Cannot divide by zero.");         if (denominator < 0) {             numerator = -numerator;             denominator = -denominator;         }         int gcd = findGCD(numerator, denominator);         this.numerator = numerator / gcd;         this.denominator = denominator / gcd;     }     private int findGCD(int a, int b) {         // work with absolute values         if (a < 0) a = -a;         if (b < 0) b = -b;         // apply Euclid's algorithm         int r = a % b;         while (r != 0) {             a = b;             b = r;             r = a % b;         }         return b;     }```
That's enough for now. Tell me if it's worth continuing.

-Gary-
• 03-28-2010, 09:43 AM
JosAH
Quote:

Originally Posted by gcalvin
That much is OK as far as it goes, but there are a couple of problems. First, denominator better not be zero. The text handles that with an ErrorException, which is part of the ACM libraries the CS106A course uses (and almost nobody else in the modern Java world seems to use), but I'll use a regular Exception for now. (We really should be subclassing our own Exception class, but we'll do that another time.) The reason why I want to do it that way is because the ACM ErrorException class sort of "swallows" the Exception instead of doing things The Java Way. Anyway, our constructor now looks like this:
Code:

```    public Rational(int numerator, int denominator) throws Exception {         if (0 == denominator) throw new Exception("Cannot divide by zero.");         this.numerator = numerator;         this.denominator = denominator;     }```
Note the "throws" clause on the top line -- that's the standard Java way of warning that a method can generate Exceptions.

Better don't do that: the zero denominator could be the result of a perfectly valid calculation; there's a perfect IllegalArgumentException for that; it is an unchecked exception.

kind regards,

Jos
• 03-28-2010, 06:39 PM
sonny
thanks all,,

like I said i kind of see pretty much what the class is doing etc,
there are a few new concepts to get my head around
such as constructors, and Ivars toString, , there are no class variables but i kind get the idea there too, so nothing really major or obscure, except maybe the 'this' thingy which requires a bit of thouight..

and i think it was as much a syntax issue, despite giving this code and explaining the concepts in text there was no explanation of how to utilse it specifically,
Quote:

your main problem is not knowing how to call the methods from the Rational class. Since the methods are not static (i.e. they're object or instance methods)
its maybe just a subtle difference like you say

okay i got 3 kids to feed, bath, and put to bed and then ill try some hard code examples, and then hopefully get the calculator working before i hit the hay myself,
if i have any problems ill post here or else mark it solved when ive done
• 03-28-2010, 06:44 PM
Fubarable
Quote:

Originally Posted by gcalvin
Sonny, this is really not beyond your grasp, and I don't believe Fubarable was trying to say that it was. He was just saying that trying to learn this class and trying to learn the complexities of console input at the same time is maybe not a great idea.

Exactly. Learn one, debug the app and get it to work, and then then learn the other, but definitely learn both! Thanks for clarifying that and sorry for the misunderstanding.
• 03-28-2010, 07:25 PM
m00nchile
Quote:

Originally Posted by sonny

and i think it was as much a syntax issue, despite giving this code and explaining the concepts in text there was no explanation of how to utilse it specifically,
its maybe just a subtle difference like you say

Acctually, I did give you a general example, and an example using Rational objects.
• 03-28-2010, 11:29 PM
sonny
Ta da!!
yeah once i got the method right with hard code it was fairly easy to then do it with user input,,
i had to think a bit about the while loop and the sequence but i got there, :D

thanks to all,:cool:

@ Gary: now I have had a bit of time to read through the thread without the ankle biters running riot, I will examine the code in the class, and your suggestions in a bit more detail, so will likley post here again on the class code

Code:

```        private void calculator() {                 Rational total = new Rational();                 String operation = ("+");                 while(!(operation.equals("="))){                         int num = readInt("  Numerator: ");                         int den = readInt("Denominator: ");                         Rational one = new Rational(num,den);                         if(operation.equals("+")) total = total.add(one);                         else if (operation.equals("-")) total = total.subtract(one);                         else if (operation.equals("x")||operation.equals("*")|operation.equals("X"))total = total.multiply(one);                         else if (operation.equals("/")) total = total.divide(one);                         operation = readLine("+, -, x, /, or = ");                         println(total);                 }```