Dado un par de números de coma flotante, ¿cuál es la mejor manera de realizar una comparación triple, es decir, devolver negativo, cero o positivo, dependiendo de si el primer número es menor, igual o mayor que el segundo número?
Algunos lenguajes como Perl, Java y C++20 tienen este operador integrado o en la biblioteca estándar. Sin embargo, estoy preguntando cómo hacer esto en C simple.
Si las entradas fueran números enteros, sería una simple cuestión de escribir un par de comparaciones bidireccionales. Pero es más complicado con entradas de punto flotante debido al comportamiento especial de los NaN en comparación. ¿Cuál es la forma adecuada de hacerlo, teniendo eso en cuenta?
Devuelve -1, 0, 1 para menor, igual y mayor, más algún otro valor para no comparable:
#include <math.h> int cmp(double a, double b) { if (isunordered(a, b)) { /* at least one NaN, return whatever you feel is appropriate */ return 42; } return (a>b) - (a<b); } Si desea comparaciones borrosas con épsilon, siéntase libre de hacer que < y > sean un poco más complicados...
¿Cuál es la forma adecuada de hacerlo, teniendo en cuenta eso (NAN)?
Devuelva un tipo de FP para permitir 4 valores de retorno diferentes: -1.0, 0.0, 1.0, NAN.
Debajo también devuelve -0.0 en casos seleccionados que involucran -0.0.
#include <math.h> double fcmp(double a, double b) { if (isunordered(a, b)) return NAN; if (a > b) return 1.0; if (a < b) return -1.0; return a - b; } Incluso consideraría propagar a o b cuando uno es NAN para mantener la carga útil de NAN. Pueden existir muchos números diferentes que no son números.
double fcmp(double a, double b) { if (isnan(a)) return a; if (isnan(b)) return b; ... } Pero echemos un vistazo a un 3-way usado para clasificar como con qsort() . Una pregunta es ¿dónde poner las NAN? Un objetivo común es ponerlos al final de la lista, es decir, todos los NAN son más grandes que otros. Para hacerlo, necesitamos comparar consistentemente , incluso si ambos operandos son NAN con diferentes cargas útiles.
// All NAN considered greater than others // return 0, a positive or negative int. int fcmp_for_qsort(const void *ap, const void *bp) { double a = *(const double *) ap; double b = *(const double *) bp; if (isnan(a)) { if (isnan(b)) { return 0; } return 1; } if (isnan(b)) -1; return (a > b) - (a < b); }