user4192303
user4192303

Reputation:

Java fraction counter with classes

I am very stuck on an assignment for some reason. I have a program that reads fractions from an input file, assigns each line to a string, and then saves the contents to the class Fraction (numerator and denominator). The fraction object is then saved into an array called fractionList.

I have another class FractionCounter that counts the occurrences of fractions in their reduced form, and if there are any repeats then the program will simply add to the integer "counter" of that object. The FractionCounter objects are stored in an object list called fracCount.

My problem is when I am adding an object to the fracCount list of FractionCounter objects. I am using a branching statement to determine whether I should add a new fraction element (one that doesn't match any of the reduced form of the other fractions in the array fracCount) to fracCount, or if I should add a value to the counter variable in an element that shares the same reduced fraction value.

Everything works except when I am trying to determine whether the faction object is a copy or not. With the code I have, my fracCount array is empty.

Here is my code

public class Fraction {
    private int numerator;
    private int denominator;

    Fraction(){ // default, no arg constructor
    }
    // constructor that initializes data
    Fraction(int numerator, int denominator){
        this.numerator = numerator;
        if(denominator > 1000){
            this.denominator = 1;
        }else if(numerator == denominator){
            this.numerator = 1;
            this.denominator = 1;
        }else if(denominator == 0){
            System.out.println("Zero is not a valid denominator");
        }else{
            this.denominator = denominator;
        }
    }
    // compares this fraction object to 'other' fraction object
    boolean equals(Fraction other){
        if(this.numerator == other.numerator && 
                this.denominator == other.denominator){
            return true;
        }else if((this.numerator / this.denominator) ==
                (other.numerator / other.denominator)){
            return true;
        }else{
            return false;
        }
    }
    // gives user access to the numerator and denominator
    public int getNumerator(){
        return this.numerator;
    }
    public int getDenominator(){
        return this.denominator;
    }   
}

public class FractionCounter extends Fraction{
    private Fraction theFraction;
    private int counter = 1;

    FractionCounter(Fraction theFraction){
        this.theFraction = theFraction;
    }
    public boolean compareAndIncrement(Fraction newFraction){
        if((theFraction.getNumerator() / theFraction.getDenominator() == 
                newFraction.getNumerator() / newFraction.getDenominator())){
            this.counter++;
            return true;
        }else if(theFraction.getDenominator() == 0 || 
                newFraction.getDenominator() == 0){
            return false;
        }else{
            return false;
        }
    }
}

public class ObjectList {
    private int N;
    private Fraction[] fractionList;
    private int numElements = 0;

    public ObjectList(int n){
        this.N = n;
        this.fractionList = new Fraction[N];
    }
    public void add(Fraction next){
        fractionList[numElements] = next;
        numElements++;
    }
    public int size(){
        return this.numElements;
    }
    public Fraction getFraction(int i){
        return fractionList[i];
    }
}

    import java.util.Scanner;
    import java.awt.List;
    import java.io.*;
    import java.util.Arrays;

    public class FractionDriver {
    public static void main(String[] args){

        // creates scanner object
        Scanner fractions = null;

        // uses scanner to import fractions file and read how many lines 
        try{
            fractions = new Scanner(new FileInputStream("fractions.txt"));
        }catch(FileNotFoundException e){
            System.out.println("Cannot find fractions.txt");
            System.exit(0);
        }

        // creates a large array that stores the text file
        String[] input = new String[100];

        int numLines = 0; // counts the number of fractions
        int numElement = 0; // counts the current index element
        while(fractions.hasNextLine()){
            input[numElement] = fractions.next();
            numElement++;
            numLines++;
        }
        fractions.close(); // closes the input stream

        // create object list of fractions
        ObjectList fractionList = new ObjectList(numLines);
        ObjectList fractCount = new ObjectList(numLines);

        int totalFractions = 0;

        for(int i = 0; i < numLines; i++){

            totalFractions++; // adds one on every new line

            // creates an array for each fraction where frac[0] is the 
            // numerator and frac[1] is the denominator
            String[] fract = input[i].split("/"); 

            // converts the string values to integers
            int numerator = Integer.parseInt(fract[0]);
            int denom = Integer.parseInt(fract[1]);

            // creates a fraction object and assigns instance variables
            Fraction f = new Fraction(numerator, denom);
            FractionCounter count = new FractionCounter(f);

            // adds the fraction to the array if the denominator
            // is not zero
            if(f.getDenominator() != 0){
                fractionList.add(f);
                for(int j = 0; j < totalFractions; j++){
                    if(fractCount.getFraction(j) != null){
                        if(!f.equals(fractCount.getFraction(j))){
                            fractCount.add(count);
                        }else{
                            count.compareAndIncrement(f);
                        }
                    }
                }
            }   
        }
    }
}

Upvotes: 2

Views: 2355

Answers (3)

Alex Salauyou
Alex Salauyou

Reputation: 14338

There is a very natural way to check if two simple fractions are equal by value without converting them to floating-point numbers.

If a/b = c/d, then ad = bc (except for b or d = 0), so:

boolean equals(Fraction other) {
    if (this.denominator == 0 || other.denominator == 0)
         return false; // undefined
    return this.numerator * other.denominator == other.numerator * this.denominator;
}

Upvotes: 3

Ivan
Ivan

Reputation: 10372

I think this is the line that is giving you problems (in the .equals method of Fraction:

 (this.numerator / this.denominator) == (other.numerator / other.denominator)

It is currently performing integer division, so 1/2 == 0 and 1/3 == 0, so your code considers EVERY fraction to already be in the list of fractions.

You'll want to perform floating point arithmetic with some sort of epsilon.

Why Are Floating Point Numbers Inaccurate?

Upvotes: 0

djna
djna

Reputation: 55897

Is the problem that you are dividing ints?

  numerator/denominator

What happens when you divide say, 4/6 and 1/7 ? With ints they will both yield 0 so you get an unexpected equality.

You can convert to double

  (double)numerator/(double)demoninator

but remember that floating point comparison for equality is not obvious, usually we test

 if ( ( oneDouble - anotherDouble ) < someTinyValue )

Upvotes: 1

Related Questions