en Redis (http://code.google.com/p/redis) hay puntuaciones asociadas a los elementos, con el fin de tomar estos elementos ordenados. Estos puntajes son dobles, incluso si muchos usuarios realmente clasifican por enteros (por ejemplo, tiempos unix).fundición duplica a números enteros con el fin de ganar velocidad
Cuando se guarda la base de datos, necesitamos escribir este disco de doble autorización. Esto es lo que se utiliza actualmente: condiciones
snprintf((char*)buf+1,sizeof(buf)-1,"%.17g",val);
Además infinito y no-A-Number se comprueban con el fin de representar también presente en el archivo de base de datos final.
Desafortunadamente la conversión de un doble en la representación de cadena es bastante lenta. Si bien tenemos una función en Redis que convierte un entero en una representación de cadena de una manera mucho más rápida. Así que mi idea era verificar si un doble se puede convertir en un entero sin pérdida de datos, y luego usar la función para convertir el entero en una cadena si esto es cierto.
Para que esto proporcione una buena aceleración, por supuesto, la prueba para la "equivalencia" entera debe ser rápida. Así que utilicé un truco que probablemente sea un comportamiento indefinido, pero que funcionó muy bien en la práctica. Algo así:
double x = ... some value ...
if (x == (double)((long long)x))
use_the_fast_integer_function((long long)x);
else
use_the_slow_snprintf(x);
En mi razonamiento el doble de fundición superior convierte el doble en un tiempo, y luego de nuevo en un entero. Si el rango se ajusta, y no hay parte decimal, el número sobrevivirá a la conversión y será exactamente el mismo que el número inicial.
Como quería asegurarme de que esto no rompería las cosas en algún sistema, me uní a #c en freenode y recibí muchos insultos;) Así que ahora estoy intentando aquí.
¿Existe una forma estándar de hacer lo que estoy tratando de hacer sin salir de ANSI C? De lo contrario, ¿se supone que el código anterior funciona en todos los sistemas Posix a los que actualmente apunta Redis? Es decir, archs donde Linux/Mac OS X/* BSD/Solaris se están ejecutando nowaday?
Lo que puedo agregar para hacer que el código sea más correcto es una verificación explícita del rango del doble antes de probar el molde.
Gracias por cualquier ayuda.
Sucks sobre los insultos, hombre. No sé la respuesta, pero espero que encuentres una. – mmr
Si ayuda, http://stackoverflow.com/questions/638376/what-is-the-most-reliable-way-of-checking-if-a-floating-point-variable-is-an-inte era un forma de verificar esto en C#. No he encontrado una versión C todavía. –
Como alternativa, ¿puedo usar modff() para verificar si la parte fraccionaria es cero? Luego verifique si el rango de la parte integral está en el rango de una longitud larga, y si es verdadero, empújelo. – antirez