Search code examples
javaarraysclasscompareto

unable to create an array of a specific object and unable to correctly use the compare to method


in this project, my goal is to sort an array of rational numbers (I have created a rational class which allows that). TO sort the array, I had to write a compareto method for the class (my class extends the comparable interface). But when i checked my compareto method, it always returns a 0 value. Also when I make an array of rational class elements, the program just keeps running at that point without outputting any results. I don't understand why? Below is my code, which also includes methods and parts :

public class MuhammadChaudryProject4 {
    public static void main(String[] args) {
        Rational a = new Rational(1, 4);
        Rational b = new Rational(1, 8);

        System.out.println(a + " + " + b + " = " + a.add(b));
        System.out.println(a + " - " + b + " = " + a.sub(b));
        System.out.println(a + " * " + b + " = " + a.mul(b));
        System.out.println(a + " / " + b + " = " + a.div(b));

        Rational[] arr = {new Rational(7, 1), new Rational(6, 1),
                      new Rational(5, 1), new Rational(4, 1),
                      new Rational(3, 1), new Rational(2, 1),
                      new Rational(1, 1), new Rational(1, 2),
                      new Rational(1, 3), new Rational(1, 4),
                      new Rational(1, 5), new Rational(1, 6),
                      new Rational(1, 7), new Rational(1, 8),
                      new Rational(1, 9), new Rational(0, 1)};

       selectSort(arr);

       for (Rational r : arr) {
            System.out.println(r);
       }

       Number n = new Rational(7, 3);

       System.out.println(n.doubleValue());
       System.out.println(n.floatValue());
       System.out.println(n.intValue());
       System.out.println(n.longValue());
       }

 public static <T extends Comparable<? super T>> void selectSort(T[] array)        
 {

      T temp;
      int mini;

      for (int i = 0; i < array.length - 1; ++i) {

          mini = i;
          for (int j = i + 1; j < array.length; ++j) {
               if (array[j].compareTo(array[mini]) < 0) {
                    mini = j;
                }
          }

         if (i != mini) {
             temp = array[i];
             array[i] = array[mini];
             array[mini] = temp;
             }
         }
         }
   }


   class Rational extends Number implements Comparable<Rational> {
       private int num, denom;


       public Rational(int num, int denom) {
           this.num = num;
           this.denom = denom;
           reduce();

        }

        public Rational add(Rational o){

            return new Rational((denom * o.num) + (o.denom * num), denom * o.denom);
        }

        public Rational sub(Rational o) {
             return new Rational((o.denom * num) - (denom * o.num), denom * o.denom);
        }

        public Rational mul(Rational o) {

            return new Rational(num * o.num, denom * o.denom);
        }

        public Rational div(Rational o) {

            return new Rational(num * o.denom, denom * o.num);
        }

        private int gcd (int num, int denom)
        {
           while (num != denom)
               if (num > denom)
                   num = num - denom;
               else
                   denom = denom - num;

               return num;
        }
        private void reduce() {
            int common = gcd(Math.abs(num), denom);
            num = num / common;
            denom = denom / common;
        }

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


        public int compareTo(Rational a) {
             if ((double)(this.num)/(double)(this.denom) > (double)(a.num)/(double)(a.denom) ){
                return 1;
            }
            if ((double)(this.num)/(double)(this.denom) < (double)(a.num)/(double)(a.denom) ){
                return -1;
             }
            else {
                return 0;
                }

         }

         public double doubleValue() {
              return((double)num/denom);
         }

        public float floatValue() {
            return((float)num/denom);
        }

        public int intValue() {
            return((int)num/denom);
        }

        public long longValue() {
            return((long)num/denom);
        }
    }

Update -- this code has the compareto fixed, thanks to @Izruo help


Solution

  • But when i checked my compareto method, it always returns a 0 value.

    When calculating the actual value of your Rational you do the following:

    double rational = (double) (this.num / this.denom);
    

    This will produce 0 for any constellation where this.num is smaller than this.denom, because the calculation itself is done in integer arithmetic and the result is converted to a double.

    To actually do the calculation you want to do, you have to convert each value, like this:

    double rational = (double) this.num / (double) this.denom;
    

    Edit

    I just tried to run your code ignoring all errors eclipse warned about. For instance, whenever I encounter compile time erros I usually don't try to execute the code, because I'm most certain something really unexpected might happen. More information below in Note.

    Also when I make an array of rational class elements, the program just keeps running at that point without outputting any results.

    Your program runs into an infinite loop inside the int gcd(int num, int denom) method with the input values num = 0 and denom = 1.

    To solve this I recommend treating 0 values, which any value with num = 0 certainly is (0 / x = 0), as a special case. In your method you should therefore add an additional check like this as the first statement:

    if(num == 0) {
        denom = 1;
        return 0;
    }
    

    Note

    The class Rational misses to implement some abstract methods. I have no idea why your code is still able to run, despite having compile errors. However, I strongly recommend to fix these errors, hence implement the following methods:

    • int intValue()
    • long longValue()
    • float floatValue()
    • double doubleValue()

    These are merely converting methods, so really easy to implement. In fact, the doubleValue() method is meant do to exactly what I explained answering the first part of your question. The other methods are just similar.