¿Cómo comparar los dobles largos con qsort y con respecto al NaN?

Cómo comparar dobles largos conqsort() y con respecto ano un número?

Al ordenar una matriz que puede contener no números, me gustaría poner todos esosNAN a un extremo de la matriz ordenada.

qsort() impone alguna restricción en la función de comparación.

La función devolverá un número entero menor que, igual o mayor que cero si se considera que el primer argumento es menor, igual o mayor que el segundo.
C11dr §7.22.5.2 3

Cuando los mismos objetos ... se pasan más de una vez a la función de comparación, los resultados serán coherentes entre sí. Es decir, paraqsort definirán unpedido total en la matriz, ... el mismo objeto siempre se comparará de la misma manera con la clave.
§7.22.5 4

a > b es falso cuandoa <= b o sia no es un número o sib No es un número. Entoncesa > b no es lo mismo que!(a <= b) ya que tienen resultados opuestos si uno de ellos es NaN.

Si la función de comparación usareturn (a > b) - (a < b);, el código devolvería 0 si uno o ambosa ob son NaN. La matriz no se ordenaría como se desea y pierde elpedido total requisito.

loslong double aspecto de este tipo es importante cuando se usan las funciones de clasificación comoint isnan(real-floating x); oint isfinite(real-floating x);. Lo séisfinite( finite_long_double_more_than_DBL_MAX) podría devolver falso. Entonces tengo preocupaciones sobre quéisnan(some_long_double) podría haceralguna cosa inesperado.

Intenté lo siguiente. Aparentemente se clasifica como se desea.

Subpregunta: Escompare() debajo suficiente para ordenar según lo deseado? ¿Alguna simplificación recomendada? Si no, ¿cómo solucionarlo? (Para esta tarea, está bien que los valores como 0.0L y -0.0L se ordenen de cualquier manera)

#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 -memcmp(fa, fb, sizeof *fa); if -0.0, 0.0 order important.
    return 0;
  }
  // At least one of *fa or *fb is NaN
  // is *fa a non-NaN?
  if (!isnan(*fa)) return -1;
  if (!isnan(*fb)) return 1;

  // both NaN
  return 0;
  // return -memcmp(fa, fb, tbd size); if NaN order important.
}

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("");
}

Salida

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,

Si supiera que la función de comparación es correcta, publicaría en Revisión de código para obtener ideas de mejora. Sin embargo, no estoy lo suficientemente seguro de que el código funcione correctamente con esos molestos NaN.

Respuestas a la pregunta(2)

Su respuesta a la pregunta