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