2010-02-03 13 views
12

Sono solo curioso di sapere cosa succede dietro la scena per convertire un double in int, ad esempio int (5666.1)? Sarà più costoso di un statico_cast di una classe figlia rispetto a un genitore? Dal momento che la rappresentazione di int e double sono fondamentalmente differenti, ci saranno dei temporanei creati durante il processo e anche costosi.Conversione doppia a int dietro la scena?

risposta

18

Qualsiasi CPU con virgola mobile nativa avrà un'istruzione per convertire i dati in virgola mobile in numeri interi. Questa operazione può richiedere da alcuni cicli a molti. Di solito ci sono registri CPU separati per FP e interi, quindi è necessario spostare successivamente il numero intero in un registro intero prima di poterlo usare. Potrebbe trattarsi di un'altra operazione, possibilmente costosa. Vedere il manuale del processore.

PowerPC in particolare non include un'istruzione per spostare un numero intero in un registro FP in un registro intero. Ci deve essere un negozio da FP alla memoria e caricare in numero intero. Si potrebbe quindi dire che viene creata una variabile temporanea.

Nel caso di nessun supporto FP hardware, il numero deve essere decodificato. formato IEEE FP è:

sign | exponent + bias | mantissa 

Per convertire, è necessario fare qualcosa di simile

// Single-precision format values: 
int const mantissa_bits = 23; // 52 for double. 
int const exponent_bits = 8; // 11 for double. 
int const exponent_bias = 127; // 1023 for double. 

std::int32_t ieee; 
std::memcpy(& ieee, & float_value, sizeof (std::int32_t)); 
std::int32_t mantissa = ieee & (1 << mantissa_bits)-1 | 1 << mantissa_bits; 
int exponent = (ieee >> mantissa_bits & (1 << exponent_bits)-1) 
      - (exponent_bias + mantissa_bits); 
if (exponent <= -32) { 
    mantissa = 0; 
} else if (exponent < 0) { 
    mantissa >>= - exponent; 
} else if (exponent + mantissa_bits + 1 >= 32) { 
    overflow(); 
} else { 
    mantissa <<= exponent; 
} 
if (ieee < 0) mantissa = - mantissa; 
return mantissa; 

cioè un paio di operazioni di bit di disimballaggio e un cambiamento.

4

C'è invariabilmente un'istruzione FPU dedicata che fa il lavoro, cvttsd2si se il generatore di codice usa il set di istruzioni Intel SSE2. È veloce, ma non veloce come un cast statico. Di solito non richiede alcun codice.

4

Il file static_cast dipende dalla generazione del codice C++ del compilatore, ma generalmente non ha costi di runtime, poiché la modifica del puntatore viene calcolata in fase di compilazione in base alle informazioni presunte nel cast.

Quando converte un double in int, su un sistema x86 il compilatore genererà un'istruzione FIST (Floating Point/Integer Conversion) e la FPU eseguirà la conversione. Questa conversione può essere implementata nel software, ed è fatta in questo modo su determinati hardware, o se il programma lo richiede. La libreria GNU MPFR è in grado di eseguire conversioni doppie a int e eseguirà la stessa conversione su tutto l'hardware.

+1

Per un x86 moderno, il compilatore può/genererà un'istruzione SSE2, non una x87. – MSalters

+0

@MSalters: dipende; alcuni compilatori "moderni" codegen ancora alla FPU x87 di default, ma sì, molti compilatori emetteranno 'cvttsd2si'. –

+0

Sì, su x86-32 non si può semplicemente presumere che esista 'cvttsd2si'. Ma ci sono compilatori che usano x86 ins deprecato per x86-64? – MSalters