2010-10-07 3 views
9
#include <stdio.h> 
#include <stdlib.h> 

float values[] = { 4, 1, 10, 9, 2, 5, -1, -9, -2,10000,-0.05,-3,-1.1 }; 

int compare (const void * a, const void * b) 
{ 
    return ((int) (*(float*)a - *(float*)b)); 
} 

int main() 
{ 

    int i; 

    qsort (values, 13, sizeof(float), compare); 

    for (i = 0; i < 13; i++) 
    { 
     printf ("%f ",values[ i ]); 
    } 
    putchar('\n'); 

    return 0; 
} 

Результат:Проблема пытается использовать функцию C QSort

-9,000000 -3,000000 -2,000000 -1,000000 -1,100000 -0,050000 1,000000 2,000000 4,000000 5,000000 9,000000 10,000000 10000,000000

Это неправильно, потому что порядок -1 и -1.1. Я считаю, что это происходит потому, что моя функция «сравнения».

Как это исправить?

Благодаря

+2

_qsort_ отлично работает. Ваш _call для qsort_ нарушен. – aaronasterling

ответ

2

округления разницы в целое вы теряете точность.

EDIT:

Изменить функцию сравнения для

return (*(float*)a >= *(float*)b) ? 1 : -1;

Edit для AndreyT: Я не думаю, что возвращение только 1 или -1 вызовет бесконечный цикл или неправильный порядок (это будет просто обменивайтесь равными значениями, которые этого не требуют).

Имея явный случай для возврата 0, будет стоить дополнительная поплавка, и они редко равны. Таким образом, сравнение для equallity может быть опущено, если скорость столкновения во входных данных мала.

+1

Не сработает. Эта функция вернет '-1' для равных значений, что означает, что для равных' a' и 'b', сравнивающих' a' с 'b', скажет, что' a AnT

+2

Yor edit ничего не изменил, за исключением того, что теперь равные значения всегда будут возвращать '1'. Стандартный 'qsort' предназначен для компаратора, который является трехзначной функцией. Как правило, невозможно уменьшить его до двухзначной функции, независимо от того, что вы делаете. Вы должны вернуть '-1, 0, + 1'. – AnT

+1

Необычно для отладочной реализации 'qsort' проверки правильности функции сравнения. Если ваша функция сравнения вернет '1' для' (a, b) 'сравнения и в то же время вернет' 1' для '(b, a)' сравнения, такая отладка 'qsort' будет обычно прерываться с помощью asserion отказ. Внедренная реализация просто приведет к неопределенному поведению. – AnT

31

Ваша функция сравнения не работает. В нем, например, говорится, что -1.0 равен (равно) -1.1, так как (int) ((-1.0) - (-1.1)) равен нулю. Другими словами, вы сами сказали qsort, что относительный порядок -1.0 и -1.1 не имеет значения. Почему вы удивлены тем, что в результате заказа эти значения не отсортированы?

В общем, вам следует избегать сравнения числовых значений путем вычитания одного из другого. Это просто не работает. Для типов с плавающей точкой это может привести к неточным результатам по нескольким различным причинам, один из которых вы только что наблюдали. Для целых типов он может переполняться.

Общая идиома для сравнения двух числовых значений a и b для qsort выглядит как (a > b) - (a < b). Помните это и используйте его. В вашем случае это будет

int compare (const void * a, const void * b) 
{ 
    float fa = *(const float*) a; 
    float fb = *(const float*) b; 
    return (fa > fb) - (fa < fb); 
} 

В коде C это может иметь смысл определить макрос

#define COMPARE(a, b) (((a) > (b)) - ((a) < (b))) 

и использовать его вместо изложив сравнения явно.

+2

+1 Должно быть больше плюсов, и это нужно принять за ответ. –

+0

'return (fa> fb) - (fa fb); 'может быть быстрее. YMMV. – chux

+0

@chux: Почему это было бы быстрее? – AnT

 Смежные вопросы

  • Нет связанных вопросов^_^