2010-06-27 18 views
15

Forse, è una domanda molto semplice ma non ho potuto ottenere la risposta. Ho cercato un po 'di tempo (ora Google pensare che sto inviando domande automatizzate http://twitter.com/michaelsync/status/17177278608) ..C++ float to int

int n = 4.35 *100; 
cout << n; 

Perché l'uscita diventano "434" al posto di "435"? 4.35 * 100 = 435 che è un valore intero e questo dovrebbe essere assegnabile alla variabile intera "n", giusto?

OPPURE Il compilatore C++ esegue il cast di 4.35 su intero prima di moltiplicarlo? Penso che non lo farà. Perché il compilatore cambia automaticamente da 4.35 a 4.34, che è ancora un galleggiante ??

Grazie.

+3

Come sarebbe il risultato 434 se 4.35 viene lanciato su un 'int' prima della moltiplicazione? Non sarebbe 400? Giusto per escludere una delle tue spiegazioni. – pmr

+0

se hai fatto 'int y = (int) (4.35 * 100);' non lo faresti - se stai per chiamare una funzione, puoi scegliere e scegliere quella appropriata per ottenere la risposta che ti serve, che tu potrebbe anche fare in C++. Ma nel codice di esempio non si sta chiamando una funzione, si sta utilizzando il typecasting implicito fornito dalla lingua. –

+2

4.35 non è esattamente rappresentabile. Il prossimo valore doppio più vicino sembra essere (nel tuo caso) 4.34999 ... che, moltiplicato per 100, risulta in 434.999 ... ed è quindi convertito in 434. – sellibitze

risposta

36

What Every Computer Scientist Should Know About Floating-Point Arithmetic

che è in realtà solo un punto di partenza, purtroppo, come allora lingue introducono le proprie manie da quando lo fanno conversioni di tipo, ecc In questo caso hai semplicemente creato una situazione in cui la costante di 4,35 può essere rappresentato con precisione, e quindi 4.35 * 100 è più simile a 434.9999999999 e il cast a int fa trunc, non round.

+0

È solo in C++? Non succede in C# .. int n = Convert.ToInt32 (4.35 * 100); Console.WriteLine (n); –

+0

Succede in C# se si esegue il cast, ma non si sta eseguendo il cast - ToInt32 round (come afferma molto chiaramente nella documentazione). Potresti arrotondare anche in C++ (beh, 'floor' o' ceil', ma aggiungere/sottrarre 0.5 per renderlo una funzione di arrotondamento) –

+0

Ok .. Capito .. grazie .. –

2

La rappresentazione interna di 4.35 risulta 4.349999999 o simile. Moltiplicando per 100 si sposta il decimale e il .9999 viene eliminato (troncato) quando si converte in int.

Modifica: cercavo il link pubblicato da Nick. :)

7

Se si esegue questa affermazione:

cout << 4.35 

dollari per ciambelle si ottiene qualcosa di simile circa 4,3499,998821 millions perché 4.35 non è esattamente rappresentabili in un galleggiante.

Quando il compilatore esegue il float su un int che tronca.

Per ottenere il comportamento vostro visto, provare:

int n = floor((4.35 * 100.0) + 0.5);

(Il trickyness con floor è perché C++ non dispone di una funzione nativa round())

0

numeri a virgola mobile don't work that way. Molti valori (la maggior parte, tecnicamente un numero infinito di ...) non possono essere memorizzati o manipolati precisamente come punto mobile. 4.35 sembrerebbe essere uno di loro. Viene memorizzato come qualcosa che in realtà è sotto 4.35, quindi il risultato.

0

Quando un float viene convertito in un int la parte frazionaria viene troncato, la conversione non richiede l'approssimazione int al float in valore.

4.35 non può essere esattamente rappresentato come un float, il numero rappresentabile più vicina è (possiamo dedurre) leggermente meno di 4,35, vale a dire 4,34,999 mila ..., così quando moltiplicato per 100 si ottiene 434,999 ...

Se si desidera convertire uno float positivo al int più vicino, è necessario aggiungere 0,5 prima di effettuare la conversione in int.

E.g.