I'm trying to add three instance methods to the public interface of class 'Fraction' that all return a 'Fraction' as a result:
add, subtraction and multiplication. is it possible to change it from my current code into instance methods?
I just can't get it to work
Here is my code:
class Fraction {
private Integer numerator;
private Integer denumerator;
public Fraction(Integer numerator, Integer denumerator) {
int gcd = 1;
for (int i = 1; i <= numerator && i <= denumerator; i++) {
if (numerator % i == 0 && denumerator % i == 0)
gcd = i;
}
this.numerator = numerator / gcd;
this.denumerator = denumerator / gcd;
}
public Fraction(Integer numerator) {
this.numerator = numerator;
this.denumerator = 1;
}
public String toString() {
return numerator + "/" + denumerator;
}
public static Fraction add(Fraction f1,Fraction f2){
return new Fraction(f1.numerator*f2.denumerator+f2.numerator*f1.denumerator,f1.denumerator*f2.denumerator);
}
public static Fraction subtract(Fraction f1,Fraction f2){
return new Fraction(f1.numerator*f2.denumerator-f2.numerator*f1.denumerator,f1.denumerator*f2.denumerator);
}
public static Fraction mul(Fraction f1,Fraction f2){
return new Fraction(f1.numerator*f2.numerator,f1.denumerator*f2.denumerator);
}
}
class Main
{
public static void main(String[] arguments)
{
final Fraction HALF = new Fraction(1, 2);
final Fraction THREE_FIFTH = new Fraction(3, 5);
System.out.println(HALF.add(HALF, THREE_FIFTH).toString());
System.out.println(THREE_FIFTH.subtract(HALF, THREE_FIFTH).toString());
System.out.println(HALF.mul(HALF, THREE_FIFTH).toString());
}
}
public static Fraction add(Fraction f1,Fraction f2){
return new Fraction(f1.numerator*f2.denumerator+f2.numerator*f1.denumerator,
f1.denumerator*f2.denumerator);
}
is a class method (because of the static it does not need an instance to call "on").
Making it instance method would look like
public Fraction add(Fraction other){
return new Fraction(this.numerator*other.denumerator+other.numerator*this.denumerator,
this.denumerator*other.denumerator);
}
of course you do not actually need to write the thiss there, just they emphasize that f1 became the current object, and f2 became the single argument.
Then you could use it as
Fraction HALF = new Fraction(1, 2);
Fraction THREE_FIFTH = new Fraction(3, 5);
System.out.println(HALF.add(THREE_FIFTH));
without repeating HALF (like HALF.add(HALF,THREE_FIFTH) in the original code).
Side comment: class methods (static stuff) can be referred via the name of the class, your original code would be more conventionally called in the form Fraction.add(...):
System.out.println(Fraction.add(HALF,THREE_FIFTH));
(System.out.println() knows that it should call toString() so you do not actually need to do that yourself)
Related
This program is supposed to create a fraction when an object is created in the main method and use other methods to add different objects. I am using a class that contains the methods for adding and multiplying the fractions. However, in the class where I have the constructor and the accessors and mutators, I also have another two methods which update the values of numerator and denominator using the methods from the previously mentioned class. How do I access the variables from said class?
This is the class with the constructor and where I am trying to import the variables:
public class Fraction {
private int numerator;
private int denominator;
public Fraction(int numerator, int denominator) {
this.numerator = numerator;
this.denominator = denominator;
}
// Getters and setters left out for brevity
// Calculate by using the FractionMath class, then update
// the numerator and denominator from the returned Fraction
public void addFraction(Fraction other) {
}
/**
* Updates this fraction by multiplying another fraction
* #param other Fraction to multiple to existing fraction
*/
//Calculate by using the FractionMath class, then update
//the numerator and denominator from the returned Fraction
public void multiplyFraction(Fraction other) {
}
public String toString() {
return numerator + " / " + denominator;
}
}
This is the class with the methods add and multiply:
public class FractionMath {
public static Fraction add(Fraction frac1, Fraction frac2) {
int numerator = frac1.getNumerator() * frac2.getDenominator() +
frac2.getNumerator() * frac1.getDenominator();
int denominator = frac1.getDenominator() * frac2.getDenominator();
return new Fraction(numerator, denominator);
}
public static Fraction multiply(Fraction frac1, Fraction frac2) {
int numerator = frac1.getNumerator() * frac2.getNumerator();
int denominator = frac1.getDenominator() * frac2.getDenominator();
return new Fraction(numerator, denominator);
}
}
Some terminology issues here: There are no static variables in your class. There are static methods.
A static variable would be public static int someNumber = 0;
It is not a static class (Such a thing doesn't really exist in Java), but a class with static methods. There are static inner classes, but they aren't really static in the way you'd have static variables or methods.
To call a static method, you'd just use the class name and the method name, e.g.
Fraction result = FractionMath.add(frac1, frac2);
I am trying to store Fraction objects in an Stack of type Number and then retrieve them to perform arithmetic calculations on them, however, the objects are being converted to type Number when I put them in the stack and I cannot convert them back to type Fraction. The compilation error occurs at line 19 of the source code below. How do I fix this?
Source code:
import java.util.Scanner;
import java.util.Stack;
public class Test{
public static void main(String[] args){
String line = "3/4";
Scanner input = new Scanner(line);
Stack<Number> numbers = new Stack<>();
while (input.hasNext()){
if (input.hasNext("/")){
numbers.push(new Fraction(input.next()));
}
}
if (numbers.peek() instanceof Fraction){
Fraction rhs = numbers.pop();
System.out.println(rhs.getFraction());
}
}
}
The Fraction class exends Number because I need to be able to store Integers, Doubles, Fractions, and Complex numbers to support inter-type mathematical operations. Note that this is not the entire Fraction class, but it is all I used for the compilation of this small test program.
public class Fraction extends Number{
private int numerator;
private int denominator;
public Fraction(String s){
this.numerator = Integer.parseInt(s.substring(0, s.indexOf("/") - 1));
this.denominator = Integer.parseInt(s.substring (s.indexOf("/") + 1, s.length() - 1));
}
public String getFraction(){
String output = this.numerator + "/" + this.denominator;
return output;
}
///Methods for retrieving and changing both the numerator and the denominator
public int getNum(){
return this.numerator;
}
public int getDenum(){
return this.denominator;
}
public void setNum(int num){
this.numerator = num;
}
public void setDenum(int denum){
this.denominator = denum;
}
public int intValue(){
return (Integer) this.numerator/this.denominator;
}
public double doubleValue(){
return this.numerator/this.denominator;
}
public long longValue(){
return this.numerator/this.denominator;
}
public short shortValue(){
return 0;
}
public float floatValue(){
return 0.0f;
}
}
This has nothing to do with Fraction. If Fraction subclasses Number then you should be able to cast from Number to Fraction. So something like
Fraction rhs = (Fraction) numbers.pop()
I have tried to write TestFraction in such a way that the main method calls on the methods getFraction1 and getFraction2 to create two Fractions: fr1 (a/b) and fr2 (a/b). getFraction1 and getFraction2 prompt the user for two integers, a and b, and call on getNumber to capture these integers. Fraction then performs calculations on fr1 and fr2. The problem is, when I run TestFraction, the values of a and b are left at 1, which is what they're set to in Fraction. Can anyone give me a hint as to why getFraction1 and getFraction2 aren't actually passing the values of a and b into fr1 and fr2?
Here is my code for TestFraction:
package Fraction;
import java.io.*;
import java.util.*;
public class TestFraction
{
static Scanner console = new Scanner (System.in);
private static int getNumber() throws InputMismatchException
{
return console.nextInt();
}
private static Fraction getFraction1()
{
int a=1, b=1;
Fraction frac = new Fraction ();
while (true) {
// prompt to enter a numerator and a denominator
System.out.println("Input 1st fraction numerator and denominator");
// input the numerator and the denominator using getNumber()
try {
a = getNumber();
b = getNumber();
}
catch (Exception e)
{
System.out.println("Exception: "+e.toString());
console.nextLine();
continue;
}
return frac;
// return new Fraction if OK
// otherwise print an error message
}
}
private static Fraction getFraction2()
{
int a=1, b=1;
Fraction frac = new Fraction ();
while (true) {
// prompt to enter a numerator and a denominator
System.out.println("Input 2nd fraction numerator and denominator");
// input the numerator and the denominator using getNumber()
try {
a = getNumber();
b = getNumber();
}
catch (Exception e)
{
System.out.println("Exception: "+e.toString());
console.nextLine();
continue;
}
return frac;
// return new Fraction if OK
// otherwise print an error message
}
}
public static void main(String[] args)
{
Fraction fr1 = new Fraction ();
fr1 = getFraction1();
Fraction fr2 = new Fraction ();
fr2 = getFraction2();
Fraction res = new Fraction();
// define other variables including res and fr2
res = Fraction.add (fr1, fr2);
System.out.println(fr1+" + "+fr2+" = "+res);
res = Fraction.subtract (fr1, fr2);
System.out.println(fr1+" - "+fr2+" = "+res);
res = Fraction.multiply (fr1, fr2);
System.out.println(fr1+" * "+fr2+" = "+res);
res = Fraction.divide (fr1, fr2);
System.out.println(fr1+" / "+fr2+" = "+res);
res = Fraction.lessThan (fr1, fr2);
System.out.println(fr1+" "+res+" "+fr2);
// test subtract, multiply, divide, lessThan methods
// each test has to print a description, a result,
// and, possibly, a error message if the calculation fails
}
}
And here is Fraction:
package Fraction;
public class Fraction
{
protected int a;
protected int b;
public Fraction()
{
a = 1;
b = 1;
}
public Fraction (int a, int b)
{
this.a=a;
this.b=b;
}
public int getNumerator()
{
return a;
}
public int getDenominator()
{
return b;
}
public void setNumerator(int a)
{
this.a=a;
}
public void setDenominator(int b)
{
this.b=b;
}
public String toString ()
{
return a+"/"+b;
}
public int gcd(int a, int b)
{
//ToDo implement Euclide algorithm
if (b==0) return a;
return gcd(b, a%b);
}
public void lowestTerms()
{
int g=gcd(a,b);
a=a/g;
b=b/g;
}
public static Fraction add(Fraction first, Fraction second)
{
Fraction result = new Fraction();
result.setNumerator(first.getNumerator()*second.getDenominator()
+ first.getDenominator()*second.getNumerator());
result.setDenominator(first.getDenominator()*second.getDenominator());
result.lowestTerms();
return result;
}
//ToDo methods subtract, multiply, divide, lessThan
public static Fraction subtract(Fraction first, Fraction second)
{
Fraction result = new Fraction();
result.setNumerator(first.getNumerator()*second.getDenominator()
- first.getDenominator()*second.getNumerator());
result.setDenominator(first.getDenominator()*second.getDenominator());
result.lowestTerms();
return result;
}
public static Fraction multiply(Fraction first, Fraction second)
{
Fraction result = new Fraction();
result.setNumerator(first.getNumerator()*second.getNumerator());
result.setDenominator(first.getDenominator()*second.getDenominator());
result.lowestTerms();
return result;
}
public static Fraction divide(Fraction first, Fraction second)
{
Fraction result = new Fraction();
result.setNumerator(first.getNumerator()*second.getDenominator());
result.setDenominator(first.getDenominator()*second.getNumerator());
result.lowestTerms();
return result;
}
public static Fraction lessThan(Fraction first, Fraction second)
{
if (first.getNumerator()*second.getDenominator() <=
first.getDenominator()*second.getNumerator()){
return first;
}
else {
return second;
}
}
}
You must use the Faction(int, int) constructor instead of Fraction() constructor:
Fraction frac = new Fraction ();
must be
Fraction frac = null;
//later in the code once you have a and b variables set and no exceptions...
frac = new Fraction (a, b);
OR use the setters:
frac.setNumerator(a);
frac.setDenominator(b);
before returning frac variable.
Looks like you are not setting the values you read from the console
a = getNumber();
b = getNumber();
frac.setNumerator(a);
frac.setDenominator(b);
by default a and b are set to 1, when you say
Fraction frac = new Fraction();
because the Fraction default constructor is defined like this
public Fraction()
{
a = 1;
b = 1;
}
I created a class that's designed to take 2 fractions, each with a numerator and denominator and add them, outputting another fraction.
When I compile the program I get an issue involving:
Fraction F3 = new Fraction.add (F1, F2); In the main method
The error: Type Fraction$add was not found
If I make everything one class the program will run but I want all the methods to be strictly in the Fraction class and calling the fractions in the UseFraction class.
import java.io.*;
import java.util.*;
import java.text.*;
public final class Fraction
{
private int numerator, denominator;
public Fraction (int numerator, int denominator) throws IllegalArgumentException
{
this.numerator = numerator;
if (denominator == 0)
{
throw new IllegalArgumentException ();
}
this.denominator = denominator;
}
//As an instance method
public void add (Fraction F)
{
this.numerator = this.numerator * F.denominator + this.denominator * F.numerator;
this.denominator = this.numerator * this.denominator;
}
//As a static method
public static Fraction add (Fraction F1, Fraction F2)
{
return new Fraction (F1.numerator * F2.denominator + F1.denominator * F2.numerator, F1.numerator);
}
//# Override
public String toString ()
{
return (this.numerator + "/" + this.denominator);
}
}
public class UseFraction
{
public static void main (String str[]) throws IOException
{
BufferedReader stdin = new BufferedReader (new InputStreamReader (System.in));
Fraction F1 = new Fraction (5, 7); // first fraction constructor
Fraction F2 = new Fraction (3, 8); // second fraction constructor
Fraction F3 = new Fraction.add (F1, F2); // addition
System.out.println ("The sum is " + F3);
}
}
Use Fraction.add(F1, F2), not new Fraction.add.
Fraction F3 = new Fraction.add (F1, F2); // addition
Should this be just:
Fraction F3 = Fraction.add (F1, F2); // addition
?
Fraction F3 = new Fraction.add (F1, F2);
Change it to:
Fraction F3 = Fraction.add (F1, F2);
public class Fraction {
private int numerator; //
private int denominator; //
Fraction(int nume, int denom)
{
numerator = nume;
denominator = denom;
}
public Fraction divide(Fraction other ) throws FractionDivideByZeroException
{
int nume=0, denom=0;
try {
nume = (this.numerator * other.denominator);
denom = (this.denominator*other.numerator);
if(nume!=0 && denom==0) throw new FractionDivideByZeroException();
return new Fraction(nume, denom);
} catch (FractionDivideByZeroException e) {
e.printError();
}
return new Fraction(nume, denom);
}
}
class FractionDivideByZeroException extends Exception
{
void printError()
{
System.out.println("You can not divide by zero!");
}
}
this is the test class:
public class FractionTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
Fraction frac1 = new Fraction(1,2);
Fraction frac2 = new Fraction(1,3);
Fraction frac3 = frac1.divide(frac2); // here's the error message saying "Unhandled exception type FractionDivideByZeroException"
System.out.println(frac3);
}
}
Take out throws declaration from your divide method. You are throwing it and then handling it there itself.
Your FractionTest uses frac1.divide and the compiler is asking you to handle the exception that is declared in the divide method.
You've said Divide throws FractionDivideByZeroException
public Fraction divide(Fraction other ) throws FractionDivideByZeroException
but written code to ensure it doesn't. The compiler doesn't know this so is complaining you/ve not handled the exception in the calling code
Look at your method signature:
public Fraction divide(Fraction other ) throws FractionDivideByZeroException
It says it throws the exception. The main method doesn't catch it, so the compiler will complain.
Catch it in the method or declare that you throw it, but not both.
I think your logic is flawed. You should never be able to create a Fraction with a zero denominator - your constructor should check that.
Your divide() method should be checking to ensure that the numerator of the divisor is not zero. That's the only way to get a divide by zero error.
When you construct the new Fraction that divide returns, the constructor should throw an exception.
Don't catch it in your divide() method; leave the throws clause and remove the try/catch. If it's a checked exception your test case has to catch it.
Here's how I'd write it:
package fraction;
public class Fraction implements Comparable
{
private int numerator;
private int denominator;
public Fraction()
{
this(0);
}
public Fraction(int numerator)
{
this(numerator,1);
}
Fraction(int numerator, int denominator)
{
if (denominator == 0)
throw new IllegalArgumentException("denominator cannot be zero");
this.numerator = numerator;
this.denominator = denominator;
if (this.numerator*this.denominator < 0)
{
this.numerator = -Math.abs(this.numerator);
this.denominator = Math.abs(this.denominator);
}
this.normalize();
}
public Fraction add(Fraction other)
{
return new Fraction(this.numerator*other.denominator+other.numerator*this.denominator, this.denominator*other.denominator);
}
public Fraction sub(Fraction other)
{
return new Fraction(this.numerator*other.denominator-other.numerator*this.denominator, this.denominator*other.denominator);
}
public Fraction mul(Fraction other)
{
return new Fraction(this.numerator*other.numerator, this.denominator*other.denominator);
}
public Fraction div(Fraction other)
{
return new Fraction(this.numerator*other.denominator, this.denominator*other.numerator);
}
#Override
public boolean equals(Object o)
{
if (this == o)
{
return true;
}
if (o == null || getClass() != o.getClass())
{
return false;
}
Fraction fraction = (Fraction) o;
if (denominator != fraction.denominator)
{
return false;
}
if (numerator != fraction.numerator)
{
return false;
}
return true;
}
#Override
public int hashCode()
{
int result = numerator;
result = 31 * result + denominator;
return result;
}
public int compareTo(Object o)
{
Fraction other = (Fraction) o;
int product1 = this.numerator*other.denominator;
int product2 = other.numerator*this.denominator;
return (product1-product2);
}
#Override
public String toString()
{
return numerator + "/" + denominator;
}
private void normalize()
{
int sign = 1;
if (this.numerator < 0)
{
sign = -1;
}
int gcd = greatestCommonDivisor(Math.abs(this.numerator), Math.abs(this.denominator));
this.numerator /= gcd;
this.denominator /= gcd;
this.numerator *= sign;
}
public static int greatestCommonDivisor(int m, int n)
{
int a = Math.max(m, n);
int b = Math.min(m, n);
if (a == 0)
return b;
if (b == 0)
return a;
while (a != b)
{
if (b > a)
b -= a;
else
a -= b;
}
return b;
}
}
And the partial unit test:
package fraction;
import org.junit.Assert;
import org.junit.Test;
public class FractionTest
{
#Test
public void testAdd()
{
Fraction x = new Fraction(3, 4);
Fraction y = new Fraction(5, 8);
Fraction expected = new Fraction(11, 8);
Assert.assertEquals(expected, x.add(y));
}
#Test
public void testSub()
{
Fraction x = new Fraction(3, 4);
Fraction y = new Fraction(5, 8);
Fraction expected = new Fraction(1, 8);
Assert.assertEquals(expected, x.sub(y));
}
#Test
public void testMul()
{
Fraction x = new Fraction(3, 4);
Fraction y = new Fraction(5, 8);
Fraction expected = new Fraction(15, 32);
Assert.assertEquals(expected, x.mul(y));
}
#Test
public void testDiv()
{
Fraction x = new Fraction(3, 4);
Fraction y = new Fraction(5, 8);
Fraction expected = new Fraction(6, 5);
Assert.assertEquals(expected, x.div(y));
}
#Test
public void testGreatestCommonDivisor()
{
Assert.assertEquals(Fraction.greatestCommonDivisor(48, 180), 12);
Assert.assertEquals(Fraction.greatestCommonDivisor(40902, 24140), 34);
Assert.assertEquals(Fraction.greatestCommonDivisor(2, 199), 1);
Assert.assertEquals(Fraction.greatestCommonDivisor(11, 8), 1);
Assert.assertEquals(Fraction.greatestCommonDivisor(1, 8), 1);
Assert.assertEquals(Fraction.greatestCommonDivisor(15, 32), 1);
Assert.assertEquals(Fraction.greatestCommonDivisor(6, 5), 1);
}
}
You stated that devide is a method that throws FractionDivideByZeroException.
your test function must catch it.
or... you function does not throw this exception so the throws FractionDivideByZeroException is redundant.
Add try/catch block to your main method. FractionDevidedByZeroException is a checked exception. You should surround them with try/catch. Otherwise you get this compilation error.
public static void main(String[] args) {
// TODO Auto-generated method stub
Fraction frac1 = new Fraction(1,2);
Fraction frac2 = new Fraction(1,3);
try {
Fraction frac3 = frac1.divide(frac2);
System.out.println(frac3);
} catch (FractionDevidedByZeroException e) {
e.printStackTrace();
}
}