Reputation:
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
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
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
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