为啥 stdlib 中的 qsort 不适用于双精度值? [C]

Posted

技术标签:

【中文标题】为啥 stdlib 中的 qsort 不适用于双精度值? [C]【英文标题】:Why qsort from stdlib doesnt work with double values? [C]为什么 stdlib 中的 qsort 不适用于双精度值? [C] 【发布时间】:2014-01-02 06:49:13 【问题描述】:

我编写了一个简单的程序来整理我的数组。问题是代码仅在我需要我的数组具有 double 元素时才使用 int 值......有什么帮助吗?

#include <stdio.h>
#include <stdlib.h>

double values[] =  88, 56, 100, 2, 25 ;

int cmpfunc (const void * a, const void * b)

    return ( *(int*)a - *(int*)b );


int main()

    int n;

    printf("Before sorting the list is: \n");
    for( n = 0 ; n < 5; n++ )
    
        printf("%.2f ", values[n]);
    

    printf("\n\n");

    qsort(values, 5, sizeof(double), cmpfunc);

    printf("\nAfter sorting the list is: \n");
    for( n = 0 ; n < 5; n++ )
    
        printf("%.2f ", values[n]);
    

    printf("\n\n");

    return(0);

工作代码:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

double values[] =  88, 56, 100, 2, 25 ;

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;


int main()

    int n;

    printf("Before sorting the list is: \n");
    for( n = 0 ; n < 5; n++ )
    
        printf("%.2f ", values[n]);
    

    printf("\n\n");

    qsort(values, 5, sizeof(double), compare);

    printf("\nAfter sorting the list is: \n");
    for( n = 0 ; n < 5; n++ )
    
        printf("%.2f ", values[n]);
    

    printf("\n\n");

    return(0);

【问题讨论】:

cmpfnc 被转换为 int* 如果你有双打,那你为什么要在比较函数中转换成 int* 呢? 您不能只说“哦,这些是整数”——它们是双精度数。尝试使用 sgn: return ( sgn((double)a - (double)b) ); @hacks 为什么你需要cmpfunc 的参数? @hacks cmpfunc 是用于qsort 的比较函数,我不知道你在说什么 【参考方案1】:

您想对双精度数进行排序,但您将它们作为整数进行比较...试试这个比较功能:

int cmpfunc (const void * a, const void * b)

  if (*(double*)a > *(double*)b)
    return 1;
  else if (*(double*)a < *(double*)b)
    return -1;
  else
    return 0;  

【讨论】:

【参考方案2】:

您错过了double* 转换吗?:

也像评论中所说的那样修复

int cmpfunc (const void * a, const void * b)

  return (*(double*)a > *(double*)b) ? 1 : (*(double*)a < *(double*)b) ? -1:0 ;

【讨论】:

那么超出整数范围的双精度数(甚至认为它们不在这里)呢?【参考方案3】:

你的比较函数是针对int而不是double

int cmpfunc (const void * a, const void * b)

    return ( *(int*)a - *(int*)b );

请注意,比较浮点数不同于比较整数值。因为浮点精度,上面把int *改成double *是不够的,应该用一个epsilon常数来比较。

http://c-faq.com/fp/fpequal.html

编辑:我删除了上面的段落,因为它与排序无关,请参阅 cmets 部分。我不会删除我的答案以保持 cmets 可见。

【讨论】:

很好,用eps 做的,也不起作用:pastie.org/private/3mwz7jt3q7zicly4j3gw 为什么需要一个 epsilon? @OliCharlesworth 如果您在浮点数组中只使用文字,那很好,但如果您的数组元素是某些计算的结果,您可能会遇到麻烦。 @ouah:不,绝对不是。使用容差比较浮点数,无论是相等还是不等,都应该在特定于应用程序的情况下使用。它不应该出现在库例程中,因为在面对错误时,没有关于什么构成相等或不相等的通用标准。根本问题实际上与平等无关。在输入不正确的情况下,无法计算 any 函数。不连续函数或具有大导数的函数会加剧这个问题,但它存在于所有函数中。 @ouah:比较函数中没有容差的排序会按顺序生成一个数字列表。带有容差的排序通常不会。因此,使用公差是错误的。

以上是关于为啥 stdlib 中的 qsort 不适用于双精度值? [C]的主要内容,如果未能解决你的问题,请参考以下文章

使用 qsort 对 long long int 数组进行排序不适用于大型 nos

为啥 gcc 给出警告:函数 qsort_r 的隐式声明?

为啥递归联合不适用于 PostgreSQL 中的复合类型

为啥条件渲染不适用于 vuejs 中的表单输入

为啥虚拟键盘不适用于 Qt 中的 QDialog 文本框?

为啥相同的语句不适用于 C++ 中的类成员?