Double to int conversion behind the scene?

2020-02-10 04:38发布

问题:

I am just curious to know what happens behind the scene to convert a double to int, say int(5666.1) ? Is that going to be more expensive than a static_cast of a child class to parent? Since the representation of the int and double are fundamentally different is there going to be temporaries created during the process and expensive too.

回答1:

Any CPU with native floating point will have an instruction to convert floating-point to integer data. That operation can take from a few cycles to many. Usually there are separate CPU registers for FP and integers, so you also have to subsequently move the integer to an integer register before you can use it. That may be another operation, possibly expensive. See your processor manual.

PowerPC notably does not include an instruction to move an integer in an FP register to an integer register. There has to be a store from FP to memory and load to integer. You could therefore say that a temporary variable is created.

In the case of no hardware FP support, the number has to be decoded. IEEE FP format is:

sign | exponent + bias | mantissa

To convert, you have to do something like

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

I.e., a few bit unpacking instructions and a shift.



回答2:

There's invariably a dedicated FPU instruction that gets the job done, cvttsd2si if the code generator uses the Intel SSE2 instruction set. That's fast, but not as fast as a static cast. That doesn't usually require any code at all.



回答3:

The static_cast is dependent on the compiler's C++ code generation, but generally has no runtime cost, as the pointer change is calculated at compile time based on the assumed information in the cast.

When you convert a double to int, on an x86 system the compiler will generate a FIST (Floating-Point/Integer Conversion) instruction, and the FPU will do the conversion. This conversion can be implemented in software, and is done this way on certain hardware, or if the program requires it. The GNU MPFR library is capable of doing double to int conversions, and will perform the same conversion on all hardware.