我试图在c中的qsort
的帮助下按降序对数组进行排序。
#include<stdio.h>
#include<stdlib.h>
int compareFloat(const void* p1, const void* p2){
const float* pa = p1;
const float* pb = p2;
return pb - pa;
}
int main()
{
float arr[] = {1.5, 1.6, 1.38};
qsort(arr, 3, sizeof(float), compareFloat);
printf("%.2f %.2f %.2f", arr[0], arr[1], arr[2]);
return 0;
}
上面代码的输出是"1.60 1.38 1.50",这是错误的;但是,当数组初始化为float arr[] = {1.38, 1.6, 1.5}
时,答案是正确的(即"1.6,1.5,1.38")。
为什么?
在比较函数
int compareFloat(const void* p1, const void* p2){
const float* pa = p1;
const float* pb = p2;
return pb - pa;
}
返回两个指针的差值。但是,您需要比较的是指向的值,而不是指针本身。
函数可以如下所示
int compareFloat( const void* p1, const void* p2)
{
float a = *( const float * )p1;
float b = *( const float * )p2;
return ( a < b ) - ( b < a );
}
这是一个示范程序。
#include <stdio.h>
#include <stdlib.h>
int compareFloat( const void *p1, const void *p2 )
{
float a = *( const float * )p1;
float b = *( const float * )p2;
return ( a < b ) - ( b < a );
}
int main( void )
{
float arr[] = { 1.5, 1.6, 1.38 };
const size_t N = sizeof( arr ) / sizeof( *arr );
qsort( arr, N, sizeof( float ), compareFloat );
printf( "%.2f %.2f %.2fn", arr[0], arr[1], arr[2] );
}
程序输出为
1.60 1.50 1.38
您的compareFloat
函数的返回值是错误的…两个原因。
首先,您正在减去指针,而不是它们指向的值-因此您需要*pb - *pa
。
1.6
和1.5
这样的值,您的测试也会失败,因为减法的结果将是非零但小于1 。因此,当转换为int
返回类型时,该函数将返回0
(表示值是相同的),即使它们不是。
您需要返回至少两次比较的结果:
int compareFloat(const void* p1, const void* p2)
{
const float* pa = p1;
const float* pb = p2;
return (*pa < *pb) - (*pa > *pb);
}
您的比较程序不正确。
return pb - pa;
你在这里减去两个指针的值。
如果处理的是整数,则应该减去指针所指向的数字:
return *pb - *pa;
但是由于小数部分被截断,这对浮点数不起作用。您需要显式地比较并返回正确的值。
if (*pa > *pb) {
return -1;
} else if (*pa < *pb) {
return 1;
} else {
return 0;
}
有人指出了以下两点不足:
-
OP的指针减法应该是浮点FP减法/比较。
-
结果需要为
int
。int compareFloat(const void* p1, const void* p2){ const float* pa = p1; const float* pb = p2; // return pb - pa; return (*pb > *pa) - (*pb < *pa); }
还有另一个问题:如果任意一个FP值可能是一个非数字NAN,则应用额外的关注来保持比较兼容。我们需要一个当参数反转时返回相反符号的排序。同样,如果a > b
和b > c
,那么a > c
。上面的(*pb > *pa) - (*pb < *pa)
不能实现nan。
int compareFloat(const void* p1, const void* p2){
const float f1 = *(const float *)p1;
const float f2 = *(const float *)p2;
if (isnan(f1)) {
if (isnan(f2)) {
// Since both are NA, just compare bit patterns
return memcmp(p1, p2, sizeof (float));
}
return 1; // Consider NAN < all non-NANs
}
if (isnan(f2)) {
return -1;
}
return (f2 > f1) - (f2 < f1);
}
int main() {
float arr[] = {1.5f, 1.6f, NAN, 1.38f}; // Better to use float constants
qsort(arr, 4, sizeof(float), compareFloat);
printf("%.2f %.2f %.2f %.2f", arr[0], arr[1], arr[2], arr[3]);
return 0;
}
输出1.60 1.50 1.38 nan