CSAPP-3e-Solutions icon indicating copy to clipboard operation
CSAPP-3e-Solutions copied to clipboard

chapter2/code/floats/float-i2f.c 我的答案

Open aQuaYi opened this issue 7 years ago • 0 comments

/** Compute (float) f. 
*/
float_bits float_i2f(int i)
{

    // 0 是 int 中的唯一的非规格化数,单独处理
    if (i == 0)
    {
        return 0x0;
    }

    // 由于 -INT_MIN = INT_MIN
    // 后面的 M 无法正确表示,单独处理
    if (i == INT_MIN)
    {
        return 0xCF000000;
    }

    unsigned sign = i < 0 ? 1 : 0;
    unsigned M = i < 0 ? -i : i;
    unsigned E = 0;

    unsigned t = M;
    while (t > 1)
    {
        t >>= 1;
        E++;
    }

    if (E <= 23) // float 可以精确表示 int
    {
        M <<= 23 - E;
    }
    else // E > 23, 需要进行取舍
    {
        unsigned trunc_mask = (unsigned)-1 >> (32 - (E - 23));
        unsigned truncation = trunc_mask & M;
        // lsb = Least Significant Bit , 最低有效位
        unsigned lsb_is_one = (M >> (E - 23)) & 1;
        unsigned half_lsb = 1 << (E - 23 - 1);
        unsigned round_to_even = (lsb_is_one && truncation >= half_lsb) ||
                                 (!lsb_is_one && truncation > half_lsb);
        M >>= E - 23;
        M += round_to_even;
        if (M == 1 << 24)
        {
            // M >>= E - 23 后,(1<<23) <= M < (1<<24)
            // 但,M += round_to_even 有可能使得 M 的最高位进一
            // 导致 M == 1 << 24 , 例如 i = INT_MAX 就会发生这种情况
            // 为了使得 (1<<23) <= M < (1<<24)
            M >>= 1;
            E++;
        }
    }

    unsigned exp = E + 127;
    unsigned frac = M - (1 << 23);

    return sign << 31 | exp << 23 | frac;
}

aQuaYi avatar Jul 30 '18 06:07 aQuaYi