2010-10-08 16 views
5

Eventuali duplicati:
Which is the first integer that an IEEE 754 float is incapable of representing exactly?Trovare il più piccolo intero che non può essere rappresentato come un-754 IEEE 32 bit a virgola mobile

In primo luogo, questa è una domanda compiti a casa, solo per cancellare questo immediatamente. Naturalmente non sto cercando una soluzione alimentata a cucchiaio, forse solo un piccolo puntatore nella giusta direzione.

Quindi, il mio compito è quello di trovare il più piccolo intero positivo che non può essere rappresentato come un IEEE-754 float (32 bit). So che il test per l'uguaglianza su qualcosa come "5 == 5,00000000001" fallirà, così ho pensato che avrei semplicemente un ciclo su tutti i numeri e di test per che in questo modo:

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; 
} 

questo non è riuscito. Poi ho cercato di sottrarre il numero intero "i" dal "risultato" a virgola mobile che è "io" sperando di ottenere qualcosa di "0,000000002" che potrei provare a rilevare, cosa che non è riuscita.

Qualcuno può indicarmi una proprietà di punti mobili su cui posso fare affidamento per ottenere la condizione di interruzione desiderata?

-------------------- Aggiornamento seguito ---------------

Grazie per aiuto su questo uno! Ho imparato più cose qui:

  1. Il mio pensiero originale era davvero corretto e determinato il risultato sulla macchina è stato progettato per essere eseguito su (Solaris 10, 32 bit), ma non ha funzionato sui miei sistemi Linux (64 bit e 32 bit).

  2. I cambiamenti che Hans Passant aggiunto realizzato il programma funziona anche con i miei sistemi, non ci sembrano essere alcune differenze di piattaforma succedendo qui che non mi aspettavo,

Grazie a tutti!

+0

Come si guasta? Quando compilo ed eseguo il tuo codice, l'output è 16777217. – Henrik

+0

@KennyTM: Accidenti, e pensavo di essere bravo a cercare! Mi dispiace per la duplicazione quindi. – LukeN

+0

@ Henrik: Continuava semplicemente a tornare indietro (INT_MAX -> 0) e non si rompeva mai con un risultato. – LukeN

risposta

5

Il problema è che il test di uguaglianza è un test a virgola mobile.La variabile i verrà convertita prima in float e ovviamente produce lo stesso valore float. Convertire il galleggiante torna a int per ottenere un test di uguaglianza intero:

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

Se inizia con le cifre 16, allora avete trovato quello giusto. Convertilo in esadecimale e spiega perché è stato quello che ha fallito per un bonus di livello.

+0

Grazie! Questo ha fatto il trucco e sono felice che la mia idea originale sia stata valida :) – LukeN

2

penso che si dovrebbe ragionare sulla rappresentazione dei numeri galleggianti come (base, segno, significante, esponente)

Ecco un estratto dalla Wikipedia che si può dare un indizio:

Un formato dato comprende:

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

(decimale). Ogni numero finito è il più semplicemente descritto da tre numeri interi: s = un segno (zero o uno), c = un significato e (o 'coefficiente'), q = un esponente. Il valore numerico di un numero finito è (-1) s × c × bq dove b è la base (2 o 10). Ad esempio, se il segno è 1 (che indica negativo), il valore e è 12345, l'esponente è -3 e la base è 10, quindi il valore del numero è -12.345.

0

Sarebbe FLT_MAX+1. Vedi float.h.

Modifica: o in realtà no. Controllare la funzione modf() in math.h

+0

No. L'hai provato? –

+0

@Hans Sì, ci sono sicuramente numeri più piccoli che non possono essere rappresentati. –

+1

Invece prova '(1 << FLT_MANT_DIG) + 1'. –

Problemi correlati