2012-03-14 15 views
56

Eventuali duplicati:
round() for float in C++C++: come arrotondare un doppio a un int?

Ho una doppia (lo chiamano x), destinato a essere 55 ma in realtà memorizzato come 54,999999999999943157 che ho appena realizzato.

Così, quando lo faccio

double x = 54.999999999999943157; 
int y = (int) x; 

y = 54 invece di 55!

Questo mi ha lasciato perplesso a lungo. Come faccio a farlo girare correttamente?

+1

È possibile aggiungere 0,5 al numero e quindi eseguire il cast per lasciarlo troncare a un int. Hai bisogno di arrotondare i numeri negativi? – Blastfurnace

+1

È possibile utilizzare questa definizione del preprocessore: '#define ROUND_2_INT (f) ((int) (f> = 0.0? (F + 0.5): (f - 0.5)))' – c00000fd

+0

In realtà 54.999999999999943157 è 8 ULP sotto _exactly rappresentable_ 55 se per 'double' intendi binary64 da IEEE 754. Quindi non è così che 55 è effettivamente memorizzato, è la conseguenza di quanto il tuo calcolo fosse impreciso. – Ruslan

risposta

85

aggiungere 0,5 prima del getto (se x> 0) o sottrarre 0.5 (se x < 0), perché il compilatore sempre troncare.

float x = 55; // stored as 54.999999... 
x = x + 0.5; // x is now 55.499999... 
int y = (int)x; // truncated to 55 

C++ 11 introduce anche std::round, che probabilmente utilizza una logica simile di aggiungere 0,5 | x | sotto il cofano (vedi il link se interessato) ma è ovviamente più robusto.

Un follow-up domanda potrebbe essere il motivo per cui il galleggiante non è memorizzato come esattamente 55. Per una spiegazione, vedere this StackOverflow risposta.

+0

Grazie ... è così semplice in realtà – midnightBlue

+0

che funzionerebbe allo stesso modo con solo int y = x + 0,5; anche se giusto? – midnightBlue

+0

Sì, penso di sì. – Moritz

31

Il casting non è un'operazione matematica e non si comporta come tale. Prova

int y = (int)round(x); 
+7

Il cast non è necessario; il risultato sarà convertito implicitamente in 'int'. –

+5

Non potrei mai ricordare le regole di promozione del tipo C e penso che non faccia male a dichiarare i cast dei tipi esplicitamente ovunque, essendo un problema così appiccicoso. –

+0

Quale libreria è 'round' parte di? AFAIK non è nella libreria standard C++. 'ceil' e' floor' sono disponibili. –

4

Il casting su un int tronca il valore. L'aggiunta di 0.5 causa l'arrotondamento corretto.

int y = (int)(x + 0.5); 
+3

non valido per i numeri negativi, come menzionato in uno dei commenti sopra. Puoi usare 'floor' invece di cast se lo stai facendo. –

3

Vale la pena notare che quello che stai facendo non è l'arrotondamento, è il casting. La trasmissione utilizzando (int) x tronca il valore decimale di x. Come nel tuo esempio, se x = 3.9995, il .9995 viene troncato e x = 3.

Come proposto da molti altri, una soluzione è aggiungere 0.5 a x e quindi eseguire il cast.

+0

Grazie, in realtà ho appena realizzato che ho bisogno di arrotondare (sto usando solo numeri interi nel mio programma) – midnightBlue

-4
#include <iostream> 
#include <cmath> 
using namespace std; 

int main() 
{ 
    double x=54.999999999999943157; 
    int y=ceil(x);//The ceil() function returns the smallest integer no less than x 
    return 0; 
} 
+5

Questo costringe i numeri verso l'alto anche se ... 54.000000000000001 diventerà 55. –

+1

@AlbertRenshaw, a destra - il che significa che questa risposta è sbagliata . –

Problemi correlati