Para dar sentido a esta pregunta, permítanme agregar una palabra – “representable” – antes de “números reales”. Dado que los números reales están representados por la mayoría de los lenguajes de programación con cierta precisión, solo hay un conjunto finito de números reales representables entre números reales finitos [math] a [/ math] y [math] b [/ math]. El formato de representación generalmente está determinado por el hardware (la CPU), que hoy sigue predominantemente el estándar de coma flotante IEEE (IEEE 754). Los dos tipos de datos más comunes son el float
32 bits y el double
64 bits. Entonces, dadas dos variables float
(o dos variables double
), ¿cómo iteramos entre todos los valores representables intermedios?
Michael Sherman señala que
C99 y C ++ 11 tienen funciones nextafter () y nexttoward () que devuelven el “siguiente valor representable” para los tipos de punto flotante. nextafter – Referencia de C ++
- ¿Cuánto se puede ocultar una imagen antes de que sea irreconocible?
- ¿Cuál es un ejemplo de un operador XOR que utiliza conceptos del mundo real?
- ¿Hay una manera eficiente de comparar la similitud de una cadena con cada permutación de otra cadena (es decir, un grupo simétrico)?
- Criptografía: ¿Qué sucedería si alguien encuentra un algoritmo significativamente más rápido para factorizar enteros grandes?
- ¿Por qué las matemáticas son importantes para la inteligencia artificial y el aprendizaje automático?
Si sabe algo sobre el estándar IEEE 754, puede profundizar en los bits (o al menos comprender cómo funcionan esas dos funciones). Ahorraré los detalles sangrientos de cómo el exponente y el significado se almacenan en IEEE 754, pero lo que importa es que la conversión de bits de los números de punto flotante en un entero con signo (en la representación de magnitud con signo) conserva el orden . En otras palabras, si toma los 32 (o 64) bits sin procesar del número de punto flotante y lo mira como si fuera un entero con signo (los tipos int o long long int respectivamente), entonces la relación entre los dos números se conserva para números positivos y para números negativos (se requiere un poco más de trabajo para manejar a <0 <b). Tenga en cuenta que la conversión de bits es muy diferente del redondeo y no corresponde a ninguna operación matemática (como el redondeo). Si observa lo que hace la conversión de bits a los números reales, el resultado parece arbitrario.
De todos modos, la propiedad de preservación del orden implica que cualquier número de punto flotante entre [math] a [/ math] y [math] b [/ math] se mapea en un entero con signo entre las variantes enteras de esos números. ¿Cómo nos ayuda el mapeo a enteros aquí? Ayuda porque para los enteros tenemos la operación “siguiente”, también conocida como i++
o i = i + 1
. Entonces, todo lo que necesitamos hacer es
- bit-cast
a, b
a enteros con signo de tamaño apropiado - incremente
a
hasta que llegue ab
- Bit-Cast una copia de cada número intermedio de vuelta al punto flotante
Para lograr la conversión de bits en el lenguaje C,
- tomar la dirección de la variable de punto flotante
- convierte el puntero a flotante resultante en un puntero a int
- desreferenciar el puntero resultante y usar el valor
En C ++, tenemos que tener más cuidado con los moldes. Cuando siga los mismos pasos, use reinterpret_cast
para la conversión del puntero.
Para manejar el caso general (incluyendo a <0 <b), verifique el bit más significativo: si es 0, hágalo 1; si 1, niega (voltea) todos los bits. Lo creas o no, tuve que escribir este código en el trabajo (para una aplicación práctica, diferente de esta pregunta).
Antes de escribir el código real, tenga en cuenta que los números de punto flotante se imprimen con una precisión bastante pequeña de forma predeterminada, por lo que cuando comience a iterar, puede parecer que el número no está cambiando. A menos que solicite específicamente imprimir esos números con la máxima precisión. En C / C ++, esto se puede lograr utilizando el formato printf
apropiado para float
o double
. Si usa la salida de flujo en C ++, necesitará el setprecision()
E / S setprecision setprecision()
.
Espero que esto ayude.