Como comparar duplas longas com qsort e com relação ao NaN?

Como comparar duplas longas comqsort() e em relação anão é um número?

Ao classificar uma matriz que pode conter números não, eu gostaria de colocar todas essasNAN para uma extremidade da matriz classificada.

qsort() impõe alguma restrição à função de comparação.

A função retornará um número inteiro menor que, igual a ou maior que zero se o primeiro argumento for considerado respectivamente menor que, igual a ou maior que o segundo.
C11dr §7.22.5.2 3

Quando os mesmos objetos ... são passados mais de uma vez para a função de comparação, os resultados devem ser consistentes entre si. Ou seja, paraqsort eles devem definir umpedido total na matriz, ... o mesmo objeto deve sempre comparar da mesma maneira com a chave.
§7.22.5 4

a > b é falso quandoa <= b ou sea não é um número ou seb não é um número. assima > b não é o mesmo que!(a <= b) como eles têm resultados opostos se um deles é NaN.

Se a função comparar usarreturn (a > b) - (a < b);, o código retornaria 0 se um ou ambosa oub são NaN. A matriz não seria classificada como desejada e perde apedido total requerimento.

olong double Esse aspecto desse tipo é importante ao usar as funções de classificação comoint isnan(real-floating x); ouint isfinite(real-floating x);. eu seiisfinite( finite_long_double_more_than_DBL_MAX) pode retornar falso. Então, eu tenho preocupações sobre o queisnan(some_long_double) pode fazeralguma coisa inesperado.

Eu tentei o abaixo. Aparentemente, classifica como desejado.

Sub-pergunta: Écompare() abaixo suficiente para classificar como desejado? Alguma simplificação recomendada? Se não - como consertar? (Para esta tarefa, não há problema em valores como 0,0L e -0,0L para classificar de qualquer maneira)

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

Resultado

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,

Se eu soubesse que a função de comparação estava correta, publicaria uma revisão de código para obter idéias de melhoria. No entanto, não estou confiante o suficiente para que o código funcione corretamente com esses NaNs irritantes.

questionAnswers(2)

yourAnswerToTheQuestion