Domanda

Quanto costa la conversione di un float in un double ? È banale come una conversione da int a long ?

EDIT: sto assumendo una piattaforma in cui float è di 4 byte e doppio è di 8 byte

È stato utile?

Soluzione

Considerazioni sulla piattaforma

Dipende dalla piattaforma utilizzata per il calcolo float. Con x87 FPU la conversione è gratuita, poiché il contenuto del registro è lo stesso: l'unico prezzo che a volte puoi pagare è il traffico di memoria, ma in molti casi non c'è nemmeno traffico, poiché puoi semplicemente utilizzare il valore senza alcuna conversione. x87 è in realtà una strana bestia in questo senso - è difficile distinguere correttamente tra float e raddoppia su di esso, poiché le istruzioni e i registri utilizzati sono gli stessi, ciò che è diverso sono le istruzioni di caricamento / memorizzazione e la precisione di calcolo stessa è controllata usando bit di stato . L'uso di calcoli misti float / doppi può comportare risultati imprevisti (e ci sono opzioni della riga di comando del compilatore per controllare il comportamento esatto e le strategie di ottimizzazione a causa di ciò).

Quando si utilizza SSE (e talvolta Visual Studio utilizza SSE per impostazione predefinita), potrebbe essere diverso, poiché potrebbe essere necessario trasferire il valore nei registri FPU o fare qualcosa di esplicito per eseguire la conversione.

Prestazioni di risparmio di memoria

Come riepilogo e risposta al tuo commento altrove: se desideri archiviare i risultati dei calcoli fluttuanti nella memoria a 32b, il risultato sarà della stessa velocità o più veloce, perché:

  • Se lo fai su x87, la conversione è gratuita - l'unica differenza sarà fstp dword [] sarà usato al posto di fstp qword [].
  • Se lo fai con SSE abilitato, potresti persino vedere un certo guadagno in termini di prestazioni, poiché alcuni calcoli float possono essere fatti con SSE una volta che la precisione del calcolo è float solo all'interno del doppio predefinito.
  • In tutti i casi il traffico di memoria è inferiore

Altri suggerimenti

Le conversioni fluttuanti per raddoppiare si verificano gratuitamente su alcune piattaforme (PPC, x86 se il tuo compilatore / runtime utilizza " all'inferno con il tipo che mi hai detto di usare, valuterò comunque tutto in doppio lungo, nyah nyah " modalità di valutazione).

In un ambiente x86 in cui la valutazione in virgola mobile viene effettivamente eseguita nel tipo specificato utilizzando i registri SSE, le conversioni tra float e double sono costose circa quanto un'aggiunta o una moltiplicazione in virgola mobile (ovvero, è improbabile che si tratti di una considerazione delle prestazioni a meno che stai facendo molto ).

In un ambiente incorporato privo di hardware in virgola mobile, possono essere alquanto costosi.

Questo è specifico per l'implementazione C ++ che stai usando. In C ++, il tipo a virgola mobile predefinito è doppio . Un compilatore dovrebbe emettere un avviso per il seguente codice:

float a = 3.45;

perché il doppio valore 3.45 viene assegnato a un float. Se devi usare float in modo specifico, aggiungi il valore con f :

float a = 3.45f;

Il punto è che tutti i numeri in virgola mobile sono per impostazione predefinita doppio . È sicuro attenersi a questo valore predefinito se non si è sicuri dei dettagli di implementazione del proprio compilatore e non si ha una comprensione significativa del calcolo in virgola mobile. Evita il cast.

Vedi anche la sezione 4.5 di Il linguaggio di programmazione C ++ .

Non riesco a immaginare che sarebbe troppo più complesso. La grande differenza tra la conversione di int in long e la conversione di float in double è che i tipi int hanno due componenti (segno e valore) mentre i numeri in virgola mobile hanno tre componenti (segno, mantissa ed esponente).

  

La precisione singola IEEE 754 è codificata   in 32 bit usando 1 bit per il segno, 8   bit per l'esponente e 23 bit per   il significato. Tuttavia, utilizza a   bit nascosto, quindi il significato è 24   bit (p = 24), anche se lo è   codificato usando solo 23 bit.

- David Goldberg, Che cosa dovrebbe sapere ogni scienziato informatico su Floating-Point aritmetica

Quindi, la conversione tra float e double manterrà lo stesso bit di segno, imposta gli ultimi 23/24 bit della mantissa del float sulla mantissa del doppio e imposta gli ultimi 8 bit dell'esponente del float sull'esponente del doppio.

Questo comportamento potrebbe persino essere garantito da IEEE 754 ... Non ho controllato, quindi non sono sicuro.

probabilmente un po 'più lento della conversione di int in long, poiché la memoria richiesta è maggiore e la manipolazione è più complessa. Un buon riferimento su problemi di allineamento della memoria

Forse questo aiuto:

#include <stdlib.h>
#include <stdio.h>
#include <conio.h>

double _ftod(float fValue)
{
  char czDummy[30];
  printf(czDummy,"%9.5f",fValue);
  double dValue = strtod(czDummy,NULL);
  return dValue;
}


int main(int argc, char* argv[])
{
  float fValue(250.84f);
  double dValue = _ftod(fValue);//good conversion
  double dValue2 = fValue;//wrong conversion
  printf("%f\n",dValue);//250.840000
  printf("%f\n",dValue2);//250.839996
  getch();
  return 0;
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top