2010-10-07 57 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 2010-10-07 23:19:50

回答

2

四捨五入的差異整數你失去精度。

編輯:

修改比較功能

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

編輯爲AndreyT:我不認爲只返回1-1會導致無限循環或不正確的排序(它會只是交換不需要它的同等價值)。

明確的情況下返回0將花費額外的浮動compatation,並且它們很少相等。因此,如果輸入數據中的衝突率很小,那麼可以省略等式的比較。

+1

不起作用。這個函數會返回等於'-1'的值,這意味着對於等於'a'和'b'比較'a'到'b'將會說'a AnT 2010-10-07 23:03:26

+2

你的編輯沒有改變任何東西,除非現在相等的值總是返回'1'。標準'qsort'設計用於三值函數的比較器。無論你做什麼,通常都不可能將其降低爲雙值功能。你必須返回'-1,0,+ 1'。 – AnT 2010-10-07 23:15:31

+1

「qsort」的調試實現檢查比較函數的正確性並不罕見。如果你的比較函數爲'(a,b)'比較返回'1',並且同時返回'1'用於'(b,a)'比較,這種調試'qsort'實現通常會立即中止失敗。非調試實現將僅產生未定義的行爲。 – AnT 2014-09-17 17:00:07

31

您的比較功能已損壞。它說,例如,-1.0等於(相當於)-1.1,因爲(int) ((-1.0) - (-1.1))爲零。換句話說,你自己告訴qsort-1.0-1.1的相對順序並不重要。爲什麼你感到驚訝,在結果排序這些值不排序?

通常,您應該避免通過從另一箇中減去數值來比較數值。它只是不起作用。對於浮點類型,它可能會由於幾種不同的原因而產生不精確的結果,其中一種是您剛纔觀察到的。對於整數類型,它可能會溢出。

比較兩個數值abqsort的通用成語看起來爲(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需要更多加號,這需要被接受爲答案。 – 2014-04-02 01:27:34

+0

'return(fa> fb) - (fa fb);'可能會更快。因人而異。 – chux 2014-11-19 20:45:16

+0

@chux:爲什麼它會更快? – AnT 2014-11-19 21:30:39