How to compare long doubles with qsort()and with respect to not-a-number ?
When sorting an array that can contain non-digits, I would like to put all those NANat one end of the sorted array.
qsort() imposes some restriction on the comparison function.
The function must return an integer less than, equal to or greater than zero, if the first argument is considered less, equal to or greater than the second.
C11dr ยง7.22.5.2 3
When the same objects ... are passed more than once to the comparison function, the results must be consistent with each other. That is, for qsortthey must determine the full ordering in the array, ... the same object will always compare the same path with the key.
ยง7.22.5 4
a > bfalse if a <= bor if ait is not a number or if bit is not a number. So, it a > bdoes not coincide with !(a <= b), because they have opposite results if one of them is NaN.
If the comparison function uses the return (a > b) - (a < b);code returns 0 if one or both a, or bis NaN. The array does not sort at will and loses the general order requirement.
long double , int isnan(real-floating x); int isfinite(real-floating x);. , isfinite( finite_long_double_more_than_DBL_MAX) false. , isnan(some_long_double) - .
. , -, .
-: compare() ? ? - ?
( 0.0L -0.0L )
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <float.h>
int compare(const void *a, const void *b) {
const long double *fa = (const long double *) a;
const long double *fb = (const long double *) b;
if (*fa > *fb) return 1;
if (*fa < *fb) return -1;
if (*fa == *fb) {
return 0;
}
if (!isnan(*fa)) return -1;
if (!isnan(*fb)) return 1;
return 0;
}
int main(void) {
long double x[] = { 0.0L / 0.0, 0.0L / 0.0, 0.0, 1.0L / 0.0, -0.0, LDBL_MIN,
LDBL_MAX, 42.0, -1.0L / 0.0, 867-5309, -0.0 };
x[0] = -x[0];
printf("unsorted: ");
size_t n = sizeof x / sizeof x[0];
for (size_t i = 0; i < n; i++) {
printf("%.3Le,", x[i]);
}
printf("\nsorted: ");
qsort(x, n, sizeof x[0], compare);
for (size_t i = 0; i < n; i++) {
printf("%.3Le,", x[i]);
}
puts("");
}
unsorted: nan,-nan,0.000e+00,inf,-0.000e+00,3.362e-4932,1.190e+4932,4.200e+01,-inf,-4.442e+03,-0.000e+00,
sorted: -inf,-4.442e+03,-0.000e+00,0.000e+00,-0.000e+00,3.362e-4932,4.200e+01,1.190e+4932,inf,nan,-nan,
, , . , NaN.