2012-01-16 12 views
13

¿Cuántos flotantes representables hay entre 0.0 y 0.5? ¿Y cuántas carrozas representables hay entre 0.5 y 1.0? Estoy más interesado en las matemáticas que hay detrás, y necesito la respuesta para floats y doubles.¿Cuántos números de coma flotante distintos en un rango específico?

+1

pista: la cantidad de bits se usan para representar ese rango fraccional? –

+1

No recuerdo la prueba de inmediato, pero puede encontrar la respuesta en http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html o http: // floating-point-gui .de /. – Crashworks

+0

no se olvide de contar -0.0 :-) – franji1

Respuesta

13

Para IEEE754 flota, esto es bastante sencillo. Encienda el Online Float Calculator y siga leyendo.

poderes Todo puros de 2 están representados por una mantisa 0, que es en realidad 1.0 debido a los implicados líder 1. El exponente es corregido por un sesgo, de modo 1 y 0.5 son, respectivamente, 1,0   × y 1,0   × , o en binario:

 S Ex + 127 Mantissa - 1    Hex 

1: 0 01111111 00000000000000000000000  0x3F800000 
     +  0 + 127 1.0 

0.5: 0 01111110 00000000000000000000000  0x3F000000 
     + -1 + 127 1.0 

Puesto que los números de coma flotante representados en esta forma están clasificadas en la misma orde r como su representación binaria, solo necesitamos tomar la diferencia del valor integral de la representación binaria y concluir que hay 0x800000   = , es decir, 8.388.608 valores de coma flotante de precisión simple en el intervalo [0.5, 1.0)

Del mismo modo, la respuesta es 2 para double y 2 para long double.

+3

... y hay '0x3F000000' representables flotantes de precisión simple entre' 0.0' y '0.5', que es más de 1 mil millones. ¡Bonito! – Arlen

1

Para 0.0..0.5: necesita preocuparse por los exponentes desde -1 hasta lo más bajo posible, y luego multiplicar cuántos obtiene el tiempo de la cantidad de valores distintos que puede representar en la mantisa.

Por cada valor en ese rango, si lo duplica, obtiene un valor en el rango de 0.5..1.0. Y doblar significa simplemente subir el exponente.

También debe preocuparse por los números no normalizados, donde la mantisa no se usa para representar 1.x, sino 0.x, y por lo tanto todos estarán en su rango inferior, pero no se pueden duplicar subiendo bruscamente el exponente (ya que un valor particular del exponente se usa para indicar que el valor no está normalizado).

+0

"Por cada valor en ese rango, si duplicarlo, obtienes un valor en el rango 0.5..1.0. " eh no necesitas * sumar * 0.5, lo que significa que todos los números debajo de 'ulp (0.5)' serán todos iguales (0.5), para el rango de 0.5..1 todos los exponentes son -1 –

+0

Oops - Estaba pensando en la otra dirección (yendo desde el rango 0.5..1.0, y reduciendo a la mitad todo, lo que TODOS se correlacionarían en el rango inferior). –

+0

Sí, pero no tendría TODOS los números, particularmente los <0.25 –

0

Esta no es una respuesta per se, pero es posible que obtenga algún kilometraje de la función nextafter. Algo como esto debe ayudar a responder a su pregunta, aunque tendrá que trabajar a cabo sus propios cálculos:

float f = 0; 
while(f < 0.5) 
    { 
    print("%f (repr: 0x%x)\n", f, *(unsigned *)&f); 
    f = nextafterf(f, 0.5); 
    } 
+0

antes de ir intentando esto ** la mitad ** de los números representables en coma flotante están entre -1 y 1 para un flotante que es 2 billones (o 1 billón entre 0 y 1) para un doble que ese número * cuadrado * si empiezas a contar estarás esperando por un tiempo –

+0

@ratchetfreak - Es verdad, pero si no conoces las matemáticas subyacentes (como yo) probablemente puedas comenzar a armar el patrón de los primeros veinte a lo sumo, y luego todo Realmente necesito saber cuáles son los puntos de inicio y fin. Pero sí, es mejor si sabes las matemáticas detrás de esto. –

2

Un número de punto flotante en formato IEEE754 está entre 0.0 (inclusive) y 0.5 (exclusivo) si y solo si el bit de signo es 0 y el exponente es < -1. Los bits de mantisa pueden ser arbitrarios. Para float, que hace 2^23 números por exponente admisible, para double 2^52. ¿Cuántos exponentes admisibles hay?Para float, el exponente mínimo para números normalizados es -126, para double es -1022, así que hay

126*2^23 = 1056964608 

float valores en [0, 0.5) y

1022*2^52 = 4602678819172646912 

double valores.

0

kerrek dio la mejor explicación :)

Sólo en caso de que aquí es el código para jugar con otros intervalos también
http://coliru.stacked-crooked.com/a/7a75ba5eceb49f84

#include <iostream> 
#include <cmath> 

template<typename T> 
unsigned long long int floatCount(T a, T b) 
{ 
    if (a > b) 
     return 0; 

    if (a == b) 
     return 1; 

    unsigned long long int count = 1; 

    while(a < b) { 
     a = std::nextafter(a, b); 
     ++count; 
    } 

    return count; 
} 

int main() 
{ 
    std::cout << "number of floats in [0.5..1.0] interval are " << floatCount(0.5f, 1.0f);  
} 

impresiones

number of floats in [0.5..1.0] interval are 8388609 
Cuestiones relacionadas