2010-10-08 22 views
5

Duplicar posibles:
Which is the first integer that an IEEE 754 float is incapable of representing exactly?Encontrar el número entero más pequeño que no puede ser representado como un 754 IEEE-flotante de 32 bits

En primer lugar, esta es una pregunta tarea, sólo para aclarar este de inmediato. No estoy buscando una solución alimentada con cuchara, por supuesto, tal vez un pequeño puntero en la dirección correcta.

lo tanto, mi tarea es encontrar el número entero positivo más pequeño que no puede ser representado como un flotador de IEEE-754 (32 bits). Yo sé que las pruebas de la igualdad en algo como "== 5 5.00000000001" fallará, así que pensé que había simplemente un bucle sobre todos los números y la prueba para que de esta manera:

int main(int argc, char **argv) 
{ 
    unsigned int i; /* Loop counter. No need to inizialize here. */ 

    /* Header output */ 
    printf("IEEE floating point rounding failure detection\n\n"); 

    /* Main program processing */ 
    /* Loop over every integer number */ 
    for (i = 0;; ++i) 
    { 
     float result = (float)i; 

     /* TODO: Break condition for integer wrapping */ 

     /* Test integer representation against the IEEE-754 representation */ 
     if (result != i) 
      break; /* Break the loop here */ 
    } 

    /* Result output */ 
    printf("The smallest integer that can not be precisely represented as IEEE-754" 
      " is:\n\t%d", i); 


    return 0; 
} 

Esto fracasó. Luego traté de restar el entero "i" del punto flotante "resultado" que está "yo" esperando lograr algo así como "0.000000002" que pude probar y detectar, que también falló.

Puede alguien señalar una propiedad de los puntos que puedo confiar para obtener la condición de corte deseada flotante?

-------------------- --------------- Actualizar continuación

Gracias por la ayuda en este ¡uno! Aprendí varias cosas aquí:

  1. Mi idea original era de hecho correcta y determinado el resultado en la máquina que estaba destinado a ser ejecutado en (Solaris 10, 32 bits), pero no funcionó en mis sistemas Linux (64 bit y 32 bit).

  2. Los cambios que se añaden hizo Hans Passant el programa también funciona con mis sistemas, parece que hay algunas diferencias de plataforma pasando aquí que no me esperaba,

Gracias a todos!

+0

¿Cómo falla? Cuando compilo y ejecuto su código, el resultado es 16777217. – Henrik

+0

@KennyTM: Maldición, ¡y pensé que era bueno para buscar! Perdón por duplicar entonces. – LukeN

+0

@Henrik: Simplemente siguió retrocediendo (INT_MAX -> 0) y nunca se rompió con un resultado. – LukeN

Respuesta

5

El problema es que su prueba de igualdad es una prueba de punto flotante.La variable i se convertirá en flotante primero y, por supuesto, produce el mismo flotante. Convertir el flotador volver a int para obtener una prueba de igualdad de número entero:

float result = (float)i; 
int truncated = (int)result; 
if (truncated != i) break; 

Si comienza con los dígitos 16 entonces has encontrado la correcta. Conviértalo en hexadecimal y explica por qué ese fue el que falló para obtener una bonificación de grado.

+0

Gracias! Esto hizo el truco y estoy feliz de que mi idea original haya demostrado ser válida :) – LukeN

2

creo que debe razonar sobre la representación de los números flotantes como (base, señal, significando, exponente)

Aquí es un extracto de Wikipedia que le puede dar una pista:

Un formato dado comprende:

* Finite numbers, which may be either base 2 (binary) or base 10 

(decimal). Cada número finito es más simplemente descrito por tres enteros: s = una señal (cero o uno), c = a significand (o 'coeficiente'), q = un exponente. El valor numérico de un número finito es (-1) s × × c bq donde b es la base (2 ó 10). Por ejemplo, si el signo es 1 (indicando negativo), el significado es 12345, el exponente es -3 y la base es 10, entonces el valor del número es -12.345.

0

Eso sería FLT_MAX+1. Ver float.h.

Editar: o de hecho no. Compruebe la función modf() en math.h

+0

No. ¿Lo has probado? –

+0

@Hans Sí, definitivamente hay números más pequeños que no se pueden representar. –

+1

En lugar de eso, intenta '(1 << FLT_MANT_DIG) + 1'. –

Cuestiones relacionadas