1. 程式人生 > >關於浮點數轉換為整數的測試

關於浮點數轉換為整數的測試

#include <stdio.h>

int main(void) {
    float flt = 1.116533e24f;

    printf("%e\n", flt);
    printf("%ld\n", (long)flt); /* wrong */
    printf("%u\n", *(unsigned long * const)&flt);   /* 將浮點數理解為整數 */

    return 0;
}
/*
 * 浮點數和整數強制型別轉換的模擬測試
 */

#include <stdio.h>

typedef int int32_t;
typedef unsigned uint32_t;
typedef unsigned char uint8_t;

static int32_t float_to_int32(float flt) {
    uint32_t ret;
    uint8_t e;

    ret = (*(uint32_t * const)&flt) & 0x007FFFFF; /* 取23位尾數 */
    e = (uint8_t)((*(uint32_t * const)&flt) >> 23); /* 取8位階碼 */

    if (ret == 0u) {
        if (e == 0u)
            return 0;
        else if (e == 0xFF) {
            puts("inf");
            return 0xFFFFFFFF;
        }
    } else {
        if (e == 0xFF) {
            puts("NaN");
            return 0;
        }
    }

    ret |= 0x00800000; /* 寫入隱藏位1 */

    if (e >= 150u)
        ret <<= e - 150u;
    else
        ret >>= 150u - e;

    if ((*(uint32_t * const)&flt) >> 31)  /* 判斷符號位 */
        ret = -ret; /* 使用一元運算子 */

    return (int32_t)ret;
}

static float int32_to_float(int32_t s32) {
    uint32_t tmp;
    uint8_t cnt;

    if (s32 == 0)
        return 0.0f;

    if ((uint32_t)s32 >> 31)
        tmp = -s32;
    else
        tmp = s32;

    while (tmp) {
        tmp >>= 1;
        cnt++;
    }

    if ((uint32_t)s32 >> 31)
        tmp = -s32;
    else
        tmp = s32;

    if (cnt > 24u)
        tmp >>= cnt - 24u;
    else
        tmp <<= 24u - cnt;

    tmp &= 0xFF7FFFFF;

    tmp |= (uint32_t)(cnt - 1u + 127u) << 23u;

    if ((uint32_t)s32 >> 31) /* 寫入符號位 */
        tmp |= 0x80000000;

    return *(float * const)&tmp;
}

int main(void) {
    float f = -3451.987f; /* 不要超過int32_t的表示範圍 */
    int32_t s32 = -1234567; /* 不要超過float的7位精度 */

    printf("%d\n", (int32_t)f);
    printf("%d\n", float_to_int32(f));

    printf("%f\n", (float)s32);
    printf("%f\n", int32_to_float(s32));

    return 0;
}