2012-06-07 4 views
12

Quando un doppio ha un valore intero 'esatto', in questo modo:Quando un duplicato con un valore intero viene lanciato su un numero intero, è garantito farlo "correttamente"?

double x = 1.0; 
double y = 123123; 
double z = -4.000000; 

E 'garantito che sarà arrotondare correttamente a 1, 123123, e -4 quando il cast in un tipo integer via (int) x , (int) y, (int) z? (E non troncare a 0, 123122 o -5 b/c di stranezze in virgola mobile). Chiedo b/c in base a this page (che riguarda fp in lua, una lingua che ha solo il doppio del suo tipo numerico per impostazione predefinita), parla di come le operazioni in interi con doppi sono esatte secondo IEEE 754, ma non sono sicuro se, quando si chiamano le funzioni C con i parametri di tipo intero, devo preoccuparmi di arrotondare i doppi manualmente, oppure si cura quando i doppi hanno valori interi esatti.

+0

Dovresti chiarire alcuni elementi qui a) per doppio intendi 8 byte o 4 byte e b) per corretto intendi che il giro va verso lo zero? – JaredPar

+0

Possibile duplicato: http://stackoverflow.com/questions/9154687/validity-of-checking-exact-value-of-preset-double – Ruben

+1

Non si verifica alcun "arrotondamento". Il cast esegue il troncamento. –

risposta

9

Sì, se il valore intero si adatta a un int.

A double A potrebbe rappresentare valori interi che non rientrano nell'intervallo per il tipo int. Ad esempio, 123123.0 non può essere convertito in un int se il tipo int ha solo 16 bit.

Non è inoltre garantito che un double possa rappresentare ogni valore che un particolare tipo può rappresentare. IEEE 754 utilizza qualcosa come 52 o 53 bit per la mantissa. Se il tuo long ha 64 bit, la conversione di un numero molto grande da long a double e viceversa potrebbe non fornire lo stesso valore.

+0

Lo standard fornisce tale garanzia per i valori la cui parte integrale può essere rappresentata nel tipo di destinazione in 6.3.1.4: "Quando un valore finito di reale fluttuazione il tipo viene convertito in un tipo intero diverso da _Bool, la parte frazionaria viene scartata (ovvero il valore viene troncato verso zero). Se il valore della parte integrale non può essere rappresentato dal tipo intero, il comportamento non viene definito. " –

+0

@DanielFischer: Grazie per il riferimento. Ho aggiornato la risposta. –

0

Sì, conterrà il valore esatto che gli viene dato perché lo inserisci in codice. A volte nei calcoli sarebbe resa ,99999999999 per esempio, ma che è a causa dell'errore nel calcolo con doppi non la sua capacità di stoccaggio

1

Sarà farlo correttamente, se veramente vale intero, che potrebbe essere certi di un alcuni contesti. Ma se il valore è il risultato di precedenti calcoli in virgola mobile, non lo si poteva facilmente sapere.

Perché non calcolare esplicitamente il valore con la funzione floor(), come in long value = floor(x + 0.5). Oppure, ancora meglio, utilizzare la funzione modf() per ispezionare per un valore intero.

+0

Se si conosce che il valore è un numero intero, non vi è alcun vantaggio nell'utilizzo della funzione floor() vs.un cast (tranne quando la lingua non ha un tipo intero, ad esempio Lua, JS.) – finnw

3

Come dichiarato da Daniel Fischer, se il valore della parte intera del doppio (nel tuo caso esattamente il doppio) è rappresentabile nel tipo a cui stai convertendo, il risultato è esatto. Se il valore non rientra nell'intervallo del tipo di destinazione, il comportamento non è definito. "Non definito" indica che lo standard consente qualsiasi comportamento: potresti ottenere il numero rappresentabile più vicino, potresti ottenere zero, potresti ricevere un'eccezione o il computer potrebbe esplodere. (Nota: mentre lo standard C consente al computer di esplodere, o addirittura di distruggere l'universo, è probabile che le specifiche del produttore impongano un limite più rigido al comportamento.)

+2

Nonostante la mia leggerezza nei confronti del comportamento indefinito, voglio sottolineare che ha gravi conseguenze. Supponiamo che tu pensi che alcuni risultati saranno errati perché sono fuori dai limiti, ma li individuerai e li scarterai dopo la conversione. Una conseguenza involontaria dell'ottimizzatore del compilatore è che, se può provare che il tuo codice ottiene un comportamento indefinito, può ottimizzare il tuo codice e tutto ciò che lo chiama, sostituendolo con uscite deliberate del programma o qualsiasi altro codice. –