【问题标题】:Double to int conversion behind the scene?Double 到 int 的转换在幕后?
【发布时间】:2010-02-03 04:30:47
【问题描述】:

我只是想知道将 double 转换为 int 的幕后发生了什么,比如 int(5666.1) ?这会比子类对父类的 static_cast 更昂贵吗?由于 int 和 double 的表示形式根本不同,因此在此过程中会创建临时变量,而且成本也很高。

【问题讨论】:

    标签: c++ floating-point double int


    【解决方案1】:

    任何具有本机浮点的 CPU 都有将浮点数转换为整数数据的指令。该操作可能需要几个周期到多个周期。通常对于 FP 和整数有单独的 CPU 寄存器,因此您还必须随后将整数移动到整数寄存器才能使用它。这可能是另一种操作,可能很昂贵。请参阅您的处理器手册。

    PowerPC 尤其不包括将 FP 寄存器中的整数移动到整数寄存器的指令。必须从 FP 存储到内存并加载到整数。因此,您可以说创建了一个临时变量。

    在没有硬件 FP 支持的情况下,数字必须被解码。 IEEE FP 格式为:

    sign | exponent + bias | mantissa
    

    要转换,您必须执行类似的操作

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

    即,一些解包指令和移位。

    【讨论】:

      【解决方案2】:

      如果代码生成器使用英特尔 SSE2 指令集,则总是有一条专用的 FPU 指令来完成工作,即 cvttsd2si。这很快,但不如静态演员表快。这通常根本不需要任何代码。

      【讨论】:

        【解决方案3】:

        static_cast 依赖于编译器的 C++ 代码生成,但通常没有运行时成本,因为指针更改是在编译时根据转换中假定的信息计算的。

        当您将 double 转换为 int 时,在 x86 系统上,编译器将生成 FIST(浮点/整数转换)指令,FPU 将执行转换。这种转换可以在软件中实现,并且在某些硬件上以这种方式完成,或者如果程序需要它。 GNU MPFR 库能够执行 double 到 int 的转换,并将在所有硬件上执行相同的转换。

        【讨论】:

        • 对于现代 x86,编译器可以/将生成 SSE2 指令,而不是 x87。
        • @MSalters:视情况而定;默认情况下,一些“现代”编译器仍将代码生成到 x87 FPU,但是是的,许多编译器会发出 cvttsd2si
        • 是的,在 x86-32 上你不能仅仅假设 cvttsd2si 存在。但是是否有编译器将已弃用的 x87 ins 用于 x86-64?
        猜你喜欢
        • 1970-01-01
        • 2011-09-14
        • 2015-10-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-02-05
        • 2013-05-31
        • 2011-05-10
        相关资源
        最近更新 更多