簡體   English   中英

嘗試使用C qsort函數時出現問題

[英]Problem trying to use the C qsort function

#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;
}

結果是:

-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的順序被改變了。 我相信它正在發生,因為我的“比較”功能。

我怎樣才能解決這個問題?

謝謝

您的比較功能已損壞。 例如,它表示-1.0等於(等價) -1.1 ,因為(int) ((-1.0) - (-1.1))為零。 換句話說,你自己告訴qsort -1.0-1.1的相對順序無關緊要。 為什么你感到驚訝的是,在結果排序中這些值沒有排序?

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

用於比較qsort兩個數值ab的通用慣用法看起來像(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)))

並使用它而不是明確地拼寫出比較。

通過將差異舍入為整數,您將失去精度。

編輯:

修改比較功能

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

為AndreyT編輯:我不認為只返回1-1將導致無限循環或錯誤排序(它只會交換不需要它的相等值)。

具有返回0的明確情況將花費額外的浮點數,並且它們很少相等。 因此,如果輸入數據中的碰撞率很小,則可以省略對等式的比較。

要通過@AnT添加到現有答案,您可以通過SortChecker自動驗證您的qsort回調:

$ LD_PRELOAD=$HOME/sortcheck-master/bin/libsortcheck.so ./a.out
a.out[7133]: qsort: comparison function is not transitive (comparison function 0x4005cd (/home/iuriig/a.out+0x4005cd), called from 0x400614 (/home/iuriig/a.out+0x400614), cmdline is "./a.out")
-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

此警告表示,對於某些輸入, compare報告x < y, y < z而不是x < z 要進一步調試此問題,請運行

export SORTCHECK_OPTIONS=raise=1

並檢查生成的codedump。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM