1

I am a beginner in Java and this is my first time using Comparable interface. I don't understand why it keeps returning zero when comparing r1 and r2. Can someone explain to me what is wrong with my code? Thank you.

public class Rational implements Comparable<Rational>{
private  int num; //numerator
private int denom; //denominator

public Rational() {
 num = 0;
 denom = 1;   
 } 

 public Rational(int num, int denom) {
 if(denom <=0 ){
     throw new ArithmeticException("You cannot divide by a non-positive  number");
 }

 this.num = num;
 this.denom = denom;
 } 

 //returns numerator of this rational number
 public int getNum() {
 return num;
 } 

 //returns denominator of this rational number
 public int getDenom() {
 return denom;
 } 

 public Rational add(Rational rhs) { 
 return new Rational(num*rhs.denom+rhs.num*denom, denom*rhs.denom); 
 } 

 public Rational subtract(Rational rhs) { 
 return new Rational(num*rhs.denom-rhs.num*denom, denom*rhs.denom); 
 } 

 public Rational multiply(Rational rhs) { 
 return new Rational(num*rhs.num, denom*rhs.denom); 
 } 

 public Rational divide(Rational rhs) { 
 return new Rational(num*rhs.denom, denom*rhs.num); 
 }  

 public String toString() {
 String result;
 if (num == 0)
 result = "0";
 else if(denom == 1)
 result = num + "";
 else
 result = num + "/" + denom;
 return result;
 }

 public int compareTo(Rational rhs){
 double r1 = ((double) getNum()/getDenom());
 double r2 =  ((double)rhs.getNum() / rhs.getDenom());
 return (int) (r1 - r2);
 }

public static void main(String[] args) {
     Rational r1 = new Rational(1, 2); // 1/2 
     Rational r2 = new Rational(3, 4); // 3/4  
     Rational result = r1.add(r2); 
     Rational result1 = r1.subtract(r2);
     Rational result2 = r1.multiply(r2);
     Rational result3 = r1.divide(r2);
     System.out.println( "r1 + r2 = " + result + "\n" + "r1 - r2 = " +    result1 + "\n" + "r1*r2 = "+ result2 + "\n" + "r1/r2 = " + result3 + "\n" + (r1.compareTo(r2)));                  
     }
}
  • 3
    It returns zero if the absolute difference between the doubles is less than 1, e.g. (1/3)-(1/2). Use `Double.compare`. – Andy Turner Feb 18 '17 at 10:40
  • you can compare `getNum()* rhs.getDenom()` and `rhs.getNum() * getDenom()` and avoid using double at all. You still want to use `long` values and `Long.compare(a, b)` – Peter Lawrey Feb 18 '17 at 10:47
  • @AndyTurner Ohh I see, thank you. –  Feb 18 '17 at 10:47

1 Answers1

2

This formula

return (int) (r1 - r2);

produces zero when the difference between r1 and r2 is less than 1, which is the case that you are testing.

Since both denominators are positive by construction of your class, you can cross-multiply and subtract without using division at all:

long a = (long)getNum() * rhs.getDenom();
long b = (long)rhs.getNum() * getDenom();
return Long.compare(a, b);

Use long to avoid overflowing on multiplication.

Sergey Kalinichenko
  • 675,664
  • 71
  • 998
  • 1,399
  • Thank you for the explanation! –  Feb 18 '17 at 10:54
  • Alright, thank you for the info. I was searching how to do that, still getting used to the site –  Feb 18 '17 at 11:02
  • "Since both denominators are positive by construction" Cross-multiplication would still work if they are negative; just not with zero. – Andy Turner Feb 18 '17 at 11:07
  • @AndyTurner That's right, it would work for two negative denominators as well. It wouldn't work if one of the denominators is negative and the other one is positive, though, because the comparison sign must be flipped. – Sergey Kalinichenko Feb 18 '17 at 11:13
  • @dasblinkenlight "It wouldn't work" Really? `(a/-b) == (-a/b)`, right? Cross-multiplying gives `(a/-b) - (-a/b) = (a*b)/(-b*b) - (-a*-b)/(-a*b) = (a*b - a*b) / (-b*b) = 0`, no? – Andy Turner Feb 18 '17 at 11:15
  • @AndyTurner `1/-3 < 1/2`, but `1*2 > 1*(-3)`. – Sergey Kalinichenko Feb 18 '17 at 11:19