1

I tried to sort an array of Products by its unit price but the result doesn't work.

typedef struct {
    int supply;
    int totalPrice;
    double unitPrice;
} Product;

int comparator(const void * a, const void * b) {
    return (*(Product*) b).unitPrice - (*(Product*) a).unitPrice;
}

int main() {
    Product m[3] = {
        {18, 75, 4.17},
        {15, 72, 4.80},
        {10, 45, 4.50}
    };
    qsort(m, 3, sizeof(Product), comparator);
    for (int i = 0; i < 3; i++) {
        printf("unitPrice=%f\n", m[i].unitPrice);
    }
}
1
  • Editing your question to also show the output would be helpful. Commented Aug 11, 2020 at 4:53

2 Answers 2

2

comparator is broken. It subtracts two double values and returns an int. Any fraction in the subtraction result is lost, so numbers less than one unit apart will be considered equal.

Fix it to return a non-zero number if the items differ.

Sign up to request clarification or add additional context in comments.

Comments

1

Returning a double value from a function which returns int type value, will result in implicit conversion of double to int and the fractional part will be discarded from returned value.

If you are using gcc compiler, try compiling with -Wconversion option, the compiler will give warning:

 warning: implicit conversion turns floating-point number into integer: 'double' to 'int' [-Wfloat-conversion]
    return (*(Product*) b).unitPrice - (*(Product*) a).unitPrice;
    ~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~
1 warning generated.

You can do:

int comparator(const void * a, const void * b) {
    double first = (*(Product*) a).unitPrice;
    double second = (*(Product*) b).unitPrice;

    if (second > first) {
        return 1;
    } else if (second < first) {
        return -1;
    }
    return 0; // second == first
}

1 Comment

It is always a code smell to compare floating point values on equality (implicitly done here) without any tolerance. I would define something like static const double TOLERANCE = 0.005; and then (second > first + TOLERANCE) and (second < first - TOLERANCE).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.