2010-02-03 11 views
12

Ich bin nur neugierig zu wissen, was hinter der Szene passiert, um ein Double in int zu konvertieren, sagen int (5666.1)? Wird das teurer als ein static_cast einer Kindklasse zum Elternteil? Da die Darstellung von int und double grundlegend anders ist, werden während des Prozesses auch Provisorien erstellt und teuer.Double to Int Konvertierung hinter der Szene?

Antwort

18

Jede CPU mit nativem Fließkommawert wird eine Instruktion haben, um Fließkommawerte in ganzzahlige Daten umzuwandeln. Dieser Vorgang kann von einigen Zyklen zu vielen dauern. Normalerweise gibt es separate CPU-Register für FP und Integer, Sie müssen also die ganze Zahl später in ein Integer-Register verschieben, bevor Sie sie verwenden können. Das könnte eine andere Operation sein, möglicherweise teuer. Siehe Ihr Prozessorhandbuch.

PowerPC enthält insbesondere keine Anweisung zum Verschieben einer Ganzzahl in einem FP-Register in ein Integer-Register. Es muss einen Speicher von FP zu Speicher geben und auf Integer laden. Sie können also sagen, dass eine temporäre Variable erstellt wurde.

Wenn keine Hardware-FP-Unterstützung vorhanden ist, muss die Nummer decodiert werden. IEEE FP-Format ist:

sign | exponent + bias | mantissa 

zu konvertieren, Sie so etwas wie

// 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; 

das heißt, ein paar Bit Auspacken Anweisungen und eine Verschiebung zu tun haben.

4

Es gibt immer einen dedizierten FPU-Befehl, der den Job erledigt, cvttsd2si, wenn der Codegenerator den Intel SSE2-Befehlssatz verwendet. Das ist schnell, aber nicht so schnell wie eine statische Besetzung. Das erfordert normalerweise keinen Code.

4

Der Befehl static_cast ist abhängig von der C++ - Codegenerierung des Compilers, hat jedoch im Allgemeinen keine Laufzeitkosten, da die Zeigeränderung zur Kompilierzeit basierend auf den angenommenen Informationen in der Besetzung berechnet wird.

Wenn Sie ein Double in int konvertieren, generiert der Compiler auf einem x86-System einen FIST (Floating-Point/Integer Conversion) Befehl, und die FPU wird die Konvertierung durchführen. Diese Konvertierung kann in Software implementiert werden und erfolgt auf diese Weise auf bestimmter Hardware oder wenn das Programm dies erfordert. Die GNU MPFR-Bibliothek kann Double-to-Int-Konvertierungen durchführen und führt dieselbe Konvertierung auf der gesamten Hardware durch.

+1

Für ein modernes x86 kann/wird der Compiler einen SSE2-Befehl erzeugen, nicht einen x87. – MSalters

+0

@MSalters: Hängt davon ab; einige "moderne" Compiler kodieren immer noch standardmäßig die x87 FPU, aber ja, viele Compiler werden 'cvttsd2si' ausgeben. –

+0

Ja, auf x86-32 kann man nicht einfach davon ausgehen, dass "cvtstsd2si" existiert. Gibt es Compiler, die die veralteten x87 ins für x86-64 verwenden? – MSalters

Verwandte Themen