Win a copy of Re-engineering Legacy Software this week in the Refactoring forum
or Docker in Action in the Cloud/Virtualization forum!

# having trouble with a fraction program

James Novak
Greenhorn
Posts: 10
Hi I've been working on this java program in class and I have to have two static methods that find the quotient of two fractions and the sum of two fractions. Everything in this program works up until the end. I have a feeling that I might be using the wrong kind of static method and i was wondering if some one could tell me how to make my code work. Both methods can only use two parameters each.

import java.util.Scanner;
/** new fraction data type, and that the faction may only be positive or zero,
*the fraction will always be in lowest terms
*
*/
public class Fraction
{
private int top; //numerator
private int bottom; //denominator

public Fraction()
{

top = 0;
bottom = 1;

}

/** The fraction () method is a default constructor that creates
* a default fraction that is equal to zero.
*
*/

public Fraction(int num, int denom)
{
if (denom == 0)
throw new IllegalArgumentException("Second argument " + denom + " cannot be zero.");
if (num < 0 || denom < 0)
throw new IllegalArgumentException("Both arguments, " + num + " and " + denom + ", cannot be negative.");
top = num;
bottom = denom;
reduce();

}
/** the method assign gives new values to the numerator and denominator
* of an existing Fraction
* @param num The value to assign to the numerator
* @param denom The value to assign to the denominator
* @exception IllegalArgumentException When the second argument is zero
* @exception IllegalArgumentException When either argument is negative
*/
public void assign(int num, int denom)
{
if (denom == 0)
throw new IllegalArgumentException("Second argument " + denom + " cannot be zero.");
if (num < 0 || denom < 0)
throw new IllegalArgumentException("Both arguments, " + num + " and " + denom + ", cannot be negative.");

top=num;
bottom=denom;
reduce();

}
/** The static multiply method returns the product
*of the two parameters
*@param f1 the first fraction to multiply
*@param f2 the second fraction to multiply
*@return The product of the f1 and f2
*/
public static Fraction multiply(Fraction f1, Fraction f2)
{
Fraction temp = new Fraction();
temp.top = f1.top * f2.top;
temp.bottom = f2.bottom * f2.bottom;
temp.reduce();
return temp;

}

private void reduce()
{
if (top == 0)
bottom = 1;
else
{
int min = (top < bottom ? top : bottom);
int gcd; //greatest common divisor
for (gcd = min; gcd > 1; --gcd)
if (top % gcd == 0 && bottom % gcd == 0)
break;
top = top / gcd;
bottom = bottom / gcd;
}
}

public void output()
{
if (top == 0)
{
System.out.print(0);
return;
}
if (top >= bottom)
{
System.out.print(top / bottom);

if (top % bottom != 0)
System.out.print(" and ");
}

if (top % bottom != 0)
System.out.print(top % bottom + "/" + bottom);
}

public void input()
{
Scanner keyboard = new Scanner(System.in);
String line = keyboard.nextLine();
int slash;
int total = line.length();
slash = -1;
for (int i = 0; i < total; ++i)
{
if (line.charAt(i) == '/')
{
slash = i;
break;
}
}
if (slash == -1)
{
System.out.println("ERROR in input");
}
else
{
String first = line.substring(0, slash);
String second = line.substring(slash + 1, total);
first = first.trim();
second = second.trim();
top = Integer.parseInt(first);
bottom = Integer.parseInt(second);
reduce();
}

}

public boolean equals(Fraction f2)
{

if (top == f2.top && bottom == f2.bottom)
return true;
else
return false;
}

public boolean lessThan(Fraction f2)

{

double temp1 = (double)top / bottom;
double temp2 = (double)f2.top / f2.bottom;

if (temp1 < temp2)
return true;
else
return false;

}

public boolean greaterThan(Fraction f2)

{

double temp1 = (double)top / bottom;
double temp2 = (double)f2.top / f2.bottom;

if (temp1 > temp2)
return true;
else
return false;

}

public static void divide(Fraction f2); //Error: Missing method body, or declare abstract

{
double quotientA = (double)top / bottom; //ERROR: cannot find symbol variable f1 or f2
double quotientB = (double)f2.top / f2.bottom; //ERROR: cannot find symbol variable f1 or f2
}

{
double newTop = (double)f2.bottom * top + f1.bottom * f2.top; //error cannot find symbol viarable f1 or f2
double newBottom = (double)bottom * f2.bottom; //error cannot find symbol variable f1 or f2
}

}

Ulf Dittmer
Rancher
Posts: 42967
73
Welcome to JavaRanch.

There are extraneous semicolons in the addition and divide method declarations.

In the future, please UseCodeTags when posting code of an length. It's unnecessarily hard to read the code as it is, making it less likely that people will bother to do so. (I would have added those tags to your post, but the code is not indented at all...)

fred rosenberger
lowercase baba
Bartender
Posts: 12086
29
Here are some general tips...

1) Please use code tags to preserve your spacing. Code that isn't indented is VERY hard to read, and most folks here will just skip it - especially if it's more than about 10 lines. you can click the 'code' button above where you type your post to have them pop in, then paste your code between them.

2) please tell us EXACTLY what the problem is. You have basically said "this doesn't work". Does it compile? Does it die when you run it? Does it run, but give strange output?

3) If you get an error message, please post the EXACT contents of that message. Those messages give HUGE hints on what the problem is. If you don't get an error message, tell us what DOES happen, and what you EXPECTED to happen.

James Novak
Greenhorn
Posts: 10
Okay the exact problems are written in the bottom few lines of the program. What I am trying to do is get the integers top.f1, top.f2, and bottom.f1, and bottom.f2 to go through mathematical computations in the program. I get the errors in those static lines that they can't be found. I was able to get them to work in booleans, but I can't get them to function now.

James Novak
Greenhorn
Posts: 10
}

public static void divide(Fraction f2); //Error: Missing method body, or declare abstract

{
double quotientA = (double)top / bottom; //ERROR: cannot find symbol variable f1 or f2
double quotientB = (double)f2.top / f2.bottom; //ERROR: cannot find symbol variable f1 or f2
}

{
double newTop = (double)f2.bottom * top + f1.bottom * f2.top; //error cannot find symbol viarable f1 or f2
double newBottom = (double)bottom * f2.bottom; //error cannot find symbol variable f1 or f2
}

}

These are the lines specifically, if this is easier. The errors that i get are next to them.

Ulf Dittmer
Rancher
Posts: 42967
73
That code still has the extra semicolons I mentioned.

Campbell Ritchie
Sheriff
Posts: 48409
56
Ulf Dittmer wrote:Welcome to JavaRanch.
Agree
. . . (I would have added those tags to your post, but the code is not indented at all...)
So would I have.

You have already been told the errors are caused by too many ;s. In particular you mustn't put a ; after the name of a method and before its first {.
Why are you using double arithmetic at all? A vulgar fraction has whole numbers as both its numerator and denominator. So you should never need floating point arithmetic in that class.
Why can't you have both numbers negative, and then call the fraction positive?Try this:Then you can use the Math.abs method and the - operator to set the signs of the two numbers.

You ought not to have so many static methods. You ought to have instance methods taking a single Fraction parameter, so you can writeI suggest you Google for "Euclid's algorithm" which is the oldest algorithm with a name. It is a much more elegant than what you have. It calculates the greatest common denominator for two numbersYour documentation comment is in the wrong place; it ought to precede what it describes, not follow it.

Find out the square root of the largest value an int can have then throw an Exception if the absolute values of top or bottom are greater than that square root (or if the absolute values remain resolutely < 0). That way you should be able to avoid an overflow error.

[Pedantic mode]Don't call a constructor a method. You shouldn't write "fraction ()" in your comment. It reads "Fraction()". In fact, if you have the documentation comment in the right place, you would miss that bit out because it will link automatically.[/Pedantic mode, but such minor errors can lose you marks]

James Novak
Greenhorn
Posts: 10

public static void divide(Fraction f2)
{
double quotientA = (double)top / bottom;
double quotientB = (double)f2.top / f2.bottom;
}

{
double newTop = (double)f2.bottom * top + bottom * f2.top;
double newBottom = (double)bottom * f2.bottom;
}

I eneded up removing the excessive ;'s and now I'm getting the following errors for the bottom and top parts of my computation. The error reads something like

"non-static variable top cannot be referenced from a static context"
OR "non-static variable top bottom be referenced from a static context"

How can I get these non static variables to work in a static?

Campbell Ritchie
Sheriff
Posts: 48409
56
Wrong question. The correct question (as I nearly asked about 2 hours ago) is,

Why have you got so many static methods?

James Novak
Greenhorn
Posts: 10
I have them because my teacher said she wanted them done that way specifically.

James Novak
Greenhorn
Posts: 10
Okay I finally got it running without an error.

I have one other task to do.

I have a program titled FractionDriver.Java which outputs the various values

What I want to do is have it print out variables quotientA and quotientB at the bottom of the text.

I also want to print out the variables newTop / newBottom.

The error that I end up getting when I compile both the driver and the other program together is that the driver cannot find the variables. What should I do to fill this gap?

fred rosenberger
lowercase baba
Bartender
Posts: 12086
29
I changed your 'quote' tags to 'code' tags'.

Your variables newTop and newBottom don't exist by the time you want to print them. I would suggest you read up on 'scope', but basically, since you declare them inside the method addition(), once that method exists they are gone.

What you might want to to is have your addition method return a fraction itself, which would then have a 'top' and a 'bottom', then print those values.

Campbell Ritchie
Sheriff
Posts: 48409
56
You can only get a Fraction back if the two values are whole numbers. I thought you had the algorithms worked out.
• Add: (n1*d2 + n2*d1)/(d1 * d2)
• Subtract: as add but with - for +
• Multiply: (n1 * n2)/(d1 * d2)
• Divide: (n1 * d2)/(n2 * d1)
• You get whole numbers which can be reduced with a greatest common denominator, as previously.

So, if you have to use static methods throughout, which looks like bad design to me, you use the following pseudocode and similarIf you always use the reduce() method in your constructor, then half that method is no longer required. Because all the values are passed as arguments, there will be no access to non-static variables in those methods.