tracebell2000
tracebell2000

Reputation: 179

Sorting an array of double in C

I'm trying to sort an array of type double in C but I am not getting the expected output. It appears to be sorting the memory addresses instead of the actual values. I have tried changing the vairables to (*grade[i]) but then I get a "invalid type argument of unary *" error. Here is the snipit of code in question.

void sortGrade(double grade[], int n){
int i, j, swapped;
double temp;
for (i = 0; i < n; ++i)
{
    for (j = i + 1; j < n; ++j)
    {
        if (grade[i] < grade[j])
        {
            temp = grade[i];
            grade[i] = grade[j];
            grade[j] = temp;
        }//end if
    }//end inner for
}//end outer for
printf("After sort:\nGrade\n");
for (i = 0; i < n; ++i)
{
    printf("%d\n", grade[i]);
}//end for
}//end sortGrade

Any help would be greatly appreciated. Full disclosure, this is for school, but the assignment has already been submitted, now I'm just trying to figure out how to actually make it work.

Upvotes: 2

Views: 6993

Answers (3)

Branislav Bil&#253;
Branislav Bil&#253;

Reputation: 51

You have to be careful when dealing with float and double. They are not 100% precise. Your sorting algorithm will break when dealing with numbers that seem the same but their smaller bits differ, since floats are just an approximation of real numbers.

If you want to compare two double variables, use this.

int areDoubleEqual(double a, double b) {
  if (fabs(a - b) <= 1000 * DBL_EPSILON * fabs(a + b)) {
      /*A and B are equal*/
      return 1;
  }
  return 0;
}

If you want to implement sorting, I would recommend using qsort. This is quick a example

#include <stdio.h>
#include <float.h>
#include <math.h>

int areDoubleEqual(double a, double b) {
    if (fabs(a - b) <= 1000 * DBL_EPSILON * fabs(a + b)) {
        /*A and B are equal*/
        return 1;
    }
    return 0;
}
/*This will sort in descending order. If you want ascending order, interchange 1 and -1*/
int compareDoubles(const void *a, const void *b) {
    double doubleA = *(double *) a;
    double doubleB = *(double *) b;
    if(areDoubleEqual(doubleA, doubleB)) {
        /*When A and B are equal, quick sort expects 0.
        For further details check documentation*/
        return 0;
    }
    /*A is bigger*/
    if((doubleA - doubleB) >
        ((fabs(doubleA) < fabs(doubleB) ? fabs(doubleB) :
        fabs(doubleA)) * DBL_EPSILON * 1000)) {
        return -1;
    }
    /*B is bigger*/
    return 1;
}

int main(void) {

    double doubles[5] = {4.3, 2.1, 10.564, 350332.323, 0.3};
    qsort(doubles, 5, sizeof(double), compareDoubles);
    for(int i = 0; i < 5; i++) {
        printf("%f ", doubles[i]);
    }
    printf("\n");

    return 0;
}

Upvotes: 1

granmirupa
granmirupa

Reputation: 2790

This should work:

   int i, j, swapped;
    double temp;
    for (i = 0; i < n; ++i)
    {
        for (j = i + 1; j < n; ++j)
        {
            if (grade[i] < grade[j])
            {
                temp = grade[i];
                grade[i] = grade[j];
                grade[j] = temp;
            }//end if
        }//end inner for
    }//end outer for
    printf("After sort:\nGrade\n");
    for (i = 0; i < n; ++i)
    {
        printf("%f\n", grade[i]);
    }//end for
    }//end sortGrade

The algorithm works. The only error was the printf:

printf("%f\n", grade[i]); //for double values

or better

printf("%lf\n", grade[i]); //for double values

Upvotes: 0

jboockmann
jboockmann

Reputation: 1025

As mentioned by @M Oehm already, you have to use %f instead of %g when printing double values. Therefore do

printf("%f\n", grade[i]);

instead of

printf("%d\n", grade[i]);

I assume that the goal was writing a sorting algorithm by hand. If not, you might want to take a look at qsort provided by stdlib. This function performs the quicksort sorting algorithm.

// qsort(array pointer, number of elements, size of one element, compare function);
qsort(grade, n, sizeof(double), compare);

In order to compare the elements you also need a compare function.

// the compare function for double values
static int compare (const void * a, const void * b)
{
  if (*(double*)a > *(double*)b) return 1;
  else if (*(double*)a < *(double*)b) return -1;
  else return 0;  
}

Upvotes: 4

Related Questions