2012-11-26 13 views
6

Sono abbastanza un novizio da c. Così, quando scrivo una demo di un piccolo gioco, affronterò un problema davvero strano.Float non cambia quando aggiungo 0.1

void testC() 
{ 
    float a = 825300160; 
    float b = a + 0.1; 
    assert(a != b); 
} 

La dichiarazione di asserzione precedente non può essere approvata. Molto strano.
Il mio ambiente è mac os ml. gcc 4.2.1

+3

'float' non ha una precisione sufficiente per distinguere tra' 825300160' e '825300160.1'. – Mysticial

+1

Un numero a virgola mobile ha circa 6 cifre decimali di precisione. (Prova invece 'double'.) –

+0

' float' di solito ha una precisione di soli 24 bit. 'a' è più grande di' 2^29', e 'b <2^(- 3)', quindi 'b' è parecchi bit oltre ciò che potrebbe influenzare' a'. –

risposta

8

La parte frazionaria di float è composta da 23 bit. Sono necessari 30 bit per rappresentare l'825300160, quindi la porzione meno significativa del numero viene eliminata. L'aggiunta di .1 non fa differenza - è necessario aggiungere circa 32 per il numero di cambiare:

float a = 825300160; 
float b = a + 31.5; 
assert(a != b); // No change is detected 
float c = a + 32; 
assert(a != c); // Change is detected 
+0

+1 Per una fantastica spiegazione del punto mobile. Vorrei conoscere bene lo standard in virgola mobile. – tjameson

+0

Quindi posso fare qualcosa al mio compilatore per evitare che questo problema accada un po '. Voglio dire se il compilatore dà un avvertimento quando faccio di nuovo la stessa cosa. O dovrei solo tenere a mente l'intervallo di float e non permettere che accada di nuovo. Grazie. –

+0

Perché io sono un programmatore Java prima, il compilatore non mi permetterà di compilare, anche se qualche minuscolo problema è nascosto nel mio codice. Quindi quando scrivo il codice c, affronterò un sacco di problemi che non ho mai pensato prima. –

6

Non c'è abbastanza precisione nel tipo float. Se hai davvero bisogno di distinguere un'aggiunta di 0.1 a un numero grande come 825300160, usa il doppio.

1

Come this site spettacoli, sia A che B sarebbero rappresentati come

0 10011100 10001001100010001010011 

nello standard IEEE per i galleggianti, dove il primo bit è il segno, gli 8 successivi sono l'esponente e il rimanente 23 la mantissa. Non c'è abbastanza spazio in quei 23 bit per rappresentare la differenza, perché l'esponente è così grande.

Problemi correlati